本关任务:用户输入两个四位数以内的整数,请你对两个整数进行四则运算(为保证除法能正确计算,输入的第二个整数不能为0),要求输出的四则运算表达式是完整对齐的。
例如,给定输入1256和20,其符合上述对齐要求的四则运算的输出格式应该如下所示(为了让空格显示的更直观,这里暂用下划线_
表示空格):
_1256 + 20___ = _____1276
_1256 - 20___ = _____1236
_1256 * 20___ = ____25120
_1256 / 20___ = _______62
相关知识
程序的输出格式对用户体验影响很大,用户往往因为输出格式不美观便抱怨软件设计的不好。
那么,如何对程序的输出格式进行控制呢?接下来我们介绍一下格式化输入输出,格式化输入输出可以用函数库stdio.h
中的 scanf 和 printf 两个函数来实现。
scanf 函数
scanf 函数按照一定的格式从键盘输入数据。函数形式为:
scanf (<格式控制串> , <参数列表>) ;
-
<格式控制串> 是一个字符串,说明了输入数据要遵循的格式;
-
<参数列表> 是存放输入数据地址的列表,有多个输入数据时,参数之间用
,
分隔。如果要把输入的数据写入一个变量,参数列表中需要使用变量的地址。获取变量地址的方法为:&变量名
,其中&
是地址运算符,其运算结果是后面的变量的地址。
例如从命令行读入一个整数、一个浮点数、一个整数,分别赋值给 num1、num2 和 num3。如下代码:
scanf(″%d%f%d″, &num1, &num2, &num3); //其中 %d 和 %f 均为转换说明符,分别表示读取的数据为整型和浮点型。
如果命令行输入为:12 34.5 678
,则该函数执行的效果是:系统读取整数12并赋值给 num1,读取浮点数34.5并赋值给 num2,读取整数678并赋值给 num3。
scanf 函数常用的转换说明符如下表(省略%
):
类型字符 | 含义 |
---|---|
d | 十进制整型量 |
o | 八进制整型量 |
x | 十六进制整型量 |
u | 无符号十进制整型 |
i | 整型 |
f | 实型的小数形式 |
e | 实型的指数形式 |
g | f 和 e 的较短形式 |
c | 字符 |
s | 字符串 |
l 或 h | 放在任何整数转换说明符之前,用于输入 short 或 long 类型数据 |
l 或 L | 放在任何浮点转换说明符之前,用于输入 double 或 long double类型数据 |
printf 的输出格式控制
printf 函数按照指定的格式向屏幕输出数据。函数形式为:
printf (<格式控制串>, <参数列表>) ;
-
<格式控制串> 一般是一个字符串,描述输出数据的格式。格式控制串可以包含3种类型的字符:格式指示符、转义字符、普通字符(除格式指示符和转义字符外的其他字符)。其中:
-
格式指示符的作用是将参数列表中相应的输出数据转换为指定的格式输出
-
转义字符按照其含义输出相应的特殊符号
-
普通字符则按照原样输出
-
-
<参数列表> 存放输出数据列表,有多个输出数据时,中间用
,
分隔。格式指示符的数量、顺序与输出数据相对应。
printf 函数执行时,根据格式控制串中的格式指示符、转义字符和普通字符等,从左到右依次进行处理:遇到普通字符,则按照原样输出;遇到转义字符,则按照其含义输出相应的符号;遇到格式指示符,则将对应的输出数据按照格式指示符指定的方式输出。
格式指示符的一般形式为:
% <标志> <域宽> <精度> <转换说明符>
其中,<标志>
、<域宽>
和<精度>
都是可选项,可以不出现。
标志
printf 函数常用的标志如下表:
标志 | 含义 |
---|---|
- | 输出在域宽内左对齐 |
+ | 在正数值之前显示一个加号,在负数值之前显示一个减号 |
空格 | 在正数值之前显示一个空格 |
# | 与八进制转换说明符 0 一起使用时,在输出值之前加 0; 与十六进制转换说明符 x 或 X 一起使用时,在输出值之前加 0x 或 0X |
0 | 用 0 填充域宽 |
注意:多个标志可以联合使用。
域宽
域宽一般为一个整数,指明了数据输出的宽度。
-
如果数据实际长度小于域宽,则数据输出右对齐,即数据仍然按照域宽规定输出,在数据左边用空格补齐;
-
如果数据实际长度大于域宽,那么系统将自动突破域宽的限制,按照数据的实际长度进行输出。
注意,负号要占据一个字符位置。如果没有指明域宽,系统则按照数据的实际长度输出。
精度
精度一般也是一个整数,对于不同类型的数据,精度的含义也不一样。
- 对于整数,精度表示至少要输出的数字个数。
如果数据实际长度小于精度,则左边用0补齐,使得数据长度等于精度;如果数据实际长度大于精度,则自动突破精度限制,按照数据的实际长度输出。省缺情况下整数的精度为1。
- 对于浮点数,有两种情况。
①如果转换说明符为 e、E 和 f,精度表示小数点后的有效位数。如果数据小数部分的实际长度小于精度,则在右边补齐0,使得小数部分长度等于精度;如果数据小数部分的实际长度大于精度,则按照精度对数据进行舍入输出;
②如果浮点数的转换说明符为 g 和 G,精度表示打印数据的最大的长度。
- 对于字符串数据,精度表示字符串输出的最大长度。
如果输出字符串的实际长度小于精度,则按照字符串的实际长度输出;如果字符串的实际长度大于精度,则按照精度截取输出字符串开头的 n 个字符(假设精度为 n )输出。
转换说明符
转换说明符指明了输出数据的类型信息。printf 函数常用的转换说明符如下表:
类型字符 | 含义 |
---|---|
d | 十进制整型量 |
o | 八进制整型量 |
x | 十六进制整型量 |
u | 无符号十进制整型 |
i | 整型 |
f | 实型的小数形式 |
e | 实型的指数形式 |
g | f 和 e 的较短形式 |
c | 字符 |
s | 字符串 |
% | 输出%本身 |
l 或 h | 放在任何整数转换说明符之前,用于输出 short 或 long 类型数据 |
L | 放在任何浮点转换说明符之前,用于输出 long double类型数据 |
例如以域宽为10、右对齐的方式输出15,然后再输出换行符(\n
):
printf("%10d\n",15);
说出结果为:________15
(这里用_
代替空格,凸显结果,即输出结果也就是在15前面补充8个空格。)
文件
文件是存储在某种长期储存设备(磁盘、光盘等)上的一段数据流。C 语言中把文件看成一个有序的字节流,每个文件都以文件结束标志( EOF )结束。
下图是包含 n 个字节的文件内容:
磁盘文件由操作系统中的文件系统统一管理,也只有文件系统才能直接操作文件。所以编写 C 程序来操作文件实际上是需要调用文件系统的接口函数来进行,我们学习文件的操作也就是学习一些 C 语言库中提供的函数。是不是感觉好简单啊:-)
。
文件类型
C 语言在对文件进行操作时,将文件分为文本文件和二进制文件。
-
文本文件:指可以用任何文字处理程序阅读和编辑的简单 ASCII 文件;
-
二进制文件:指一般含有特殊的格式或计算机代码,如图形文件和可执行文件等。
下面我们本章节所学的操作都是针对文本文件而言。
文件的操作
C 语言中对文件的操作一般分为三个步骤:打开文件、读写文件、关闭文件。
打开文件后,操作系统为文件建立一个文件控制结构(文件控制块),并在内存中建立一个缓冲区,该缓冲区的数据对应文件的数据,之后的文件读写操作实际上是在缓冲区中进行。
通过文件控制块实现文件的输入输出。
将文件缓冲区中的数据写回到磁盘文件中,并释放文件控制块。
操作文件的函数
用 FILE 结构操作文件是 C 语言提供的文件操作方式,只要包含头文件stdio.h
就能使用文件操作的相关函数。下面就给大家介绍一些函数的使用。
打开文件
fopen 是stdio.h
提供的文件打开函数。
如下面的程序可以打开一个文件用于读:
#include <stdio.h>
FILE *fp = fopen("a.txt","r"); // 打开一个供读取数据的文件a.txt。
其中函数的第一个参数是拟打开文件的路径和名字,可以包含相对路径或者绝对路径,如上面程序中就是打开当前目录下的a.txt
文件。第二个参数是打开方式,fopen
函数可以使用的打开方式如下表:
打开方式 | 描述 |
---|---|
r | 打开一个供读取数据的文件 |
w | 建立或打开一个供写入数据的文件,如果该文件已经存在,则废弃文件内容 |
a | 建立或打开一个供写入数据的文件,如果文件已经存在,则写入的数据将追加到文件的尾部 |
r+ | 打开一个已存在的文件,该文件可以写入和读出数据 |
w+ | 建立或打开一个可供读和写的文件,如果文件已存在,则废弃文件内容 |
a+ | 建立或打开一个可供读和写的文件,如果文件已存在,则写入的数据追加到文件的尾部 |
b | 打开一个二进制文件 |
如果文件打开成功,函数 fopen 将返回一个指向 FILE 结构的指针,该指针指向的 FILE 结构管理了被打开的那个文件。
如果文件打开失败(如打开一个不存在的文件用于读),那么该函数将返回 NULL。上面的程序将返回值赋值给FILE*
的指针 fp ,之后就可以通过 fp 来操作打开的文件了。
读写文件
int fgetc(FILE *stream);
该函数表示从文件指针 stream 指向的文件的当前位置读取一个字符,并以 int 类型返回。
char *fgets(char *string, int n, FILE *stream);
该函数表示从文件指针 stream 指向的文件的当前位置开始读取字符串,直到遇到换行符(读入该换行符),或到达文件结束位置,或读取了 n-1 个字符。读取的字符串存入 string 所指的内存单元中,并在所有读取的字符之后添加字符串结束标记\0
。
如果读取成功,函数返回 string,如果出错或读取前已经到达了文件结束的位置,将返回 NULL。
int fscanf(FILE *stream, const char *format [,argument]...);
该函数的功能是从指定文件中将数据按照格式控制串 format 读出并转换成相应的类型以存入对应的参数中。如果读取成功,该函数返回转换成功的参数的个数,如果出错或读取前已经到达了文件结束的位置,将返回文件结束标志 EOF。
函数 fscanf 与 scanf 函数非常相似,只是 fscanf 函数多了一个参数 stream 以指向要读取数据的文件。
int fprintf(FILE *stream, const char *format [,argument]…);
该函数的功能是将数据按照格式控制串 format 写入到文件指针 stream 指向的文件中。如果写入成功,函数返回写入的字节数,否则返回一个负数表示错误。
函数 fprintf 与 printf 函数相似,只是 fprintf 函数多了一个参数 stream 以表示要写入数据的文件。
关闭文件
使用 fclose 函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。
函数原型为:
int fclose(FILE *fp);
如果流成功关闭,fclose 返回0,否则返回 EOF(−1)。(如果流为NULL,而且程序可以继续执行,fclose设定error number给EINVAL,并返回EOF。)
例如:
#include <stdio.h>
int main(){
FILE *fp;
fp = fopen("a.txt", "w");
fprintf(fp, "%s", "www.educoder.net");
fclose(fp);
return(0);
}
-
文件
文件是存储在某种长期储存设备(磁盘、光盘等)上的一段数据流。C 语言中把文件看成一个有序的字节流,每个文件都以文件结束标志( EOF )结束。
下图是包含 n 个字节的文件内容:
磁盘文件由操作系统中的文件系统统一管理,也只有文件系统才能直接操作文件。所以编写 C 程序来操作文件实际上是需要调用文件系统的接口函数来进行,我们学习文件的操作也就是学习一些 C 语言库中提供的函数。是不是感觉好简单啊
:-)
。文件类型
C 语言在对文件进行操作时,将文件分为文本文件和二进制文件。
-
文本文件:指可以用任何文字处理程序阅读和编辑的简单 ASCII 文件;
-
二进制文件:指一般含有特殊的格式或计算机代码,如图形文件和可执行文件等。
- 打开文件
- 读写文件
- 关闭文件
#include <stdio.h>
FILE *fp = fopen("a.txt","r"); // 打开一个供读取数据的文件a.txt。
- 从文本文件中读取一个字符可以使用 fgetc 函数:
int fgetc(FILE *stream);
- 从文本文件读取一行可以使用 fgets 函数:
char *fgets(char *string, int n, FILE *stream);
- 从文本文件中进行格式化读取可以使用 fscanf 函数:
int fscanf(FILE *stream, const char *format [,argument]...);
- 输出格式化数据到文本文件中可以使用 fprintf 函数:
int fprintf(FILE *stream, const char *format [,argument]…);
int fclose(FILE *fp);
#include <stdio.h>
int main(){
FILE *fp;
fp = fopen("a.txt", "w");
fprintf(fp, "%s", "www.educoder.net");
fclose(fp);
return(0);
}