printf() 函数和 scanf() 函数,它们是输入/输出函数,或简称为 I/O 函数。
虽然 printf() 是输出函数, scanf() 是输入函数,但是它们的工作原理几乎相同
一、printf() 函数
请求 printf() 函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用 %d ,打印字符时使用 %c 。这些符号被称为转换说明(conversion specification ),它们指定了如何把数据转换成可显示的形式。
转换说明及其打印的输出结果:
二、使用 printf()
printf() 函数的格式:
printf( 格式字符串, 待打印项1, 待打印项2,...);
待打印项 1 、待打印项 2 等都是要打印的项。它们可以是变量、常量,甚至是在打印之前先要计算的表达式。
格式字符串应包含每个待打印项对应的转换说明。格式字符串是双引号括起来的内容。
注意:格式字符串中的转换说明一定要与后面的每个项相匹配,若忘记这个基本要求会导致严重的后果。
如果只打印短语或句子,就不需要使用任何转换说明。
由于 printf() 函数使用 % 符号来标识转换说明,因此打印 % 符号就成了个问题。如果单独使用一个% 符号,编译器会认为漏掉了一个转换字符。解决方法很简单,使用两个 % 符号就行了。
pc = 2*6 ;
printf("Only %d %% of Sally's gribbles were edible.\n", pc);
下面是输出结果:
Only 12% of Sally's gribbles were edible.
三、printf() 的转换说明修饰符
printf() 的修饰符:
printf() 的标记:
1.使用修饰符和标记的示例
#include <stdio.h> #define PAGES 959 int main() { printf("*%d*\n", PAGES); printf("*%2d*\n", PAGES); printf("*%10d*\n", PAGES); printf("*%-10d*\n", PAGES); return 0; }
输出结果:(程序中使用星号(*)标出每个字段的开始和结束。)
*959*
*959* // 其对应的输出结果应该是 2 字段宽度
// 因为待打印的整数有 3 位数字,所以字段宽度自动扩大以符合整数的长度。
* 959* // 其对应的输出结果有10 个空格宽度 在两个星号之间有 7 个空格和 3 位数字
*959 * // - 标记说明打印的数字位于字段的左侧。
#include <stdio.h> int main() { const double RENT = 3852.99; // const变量 printf("*%f*\n", RENT); printf("*%e*\n", RENT); printf("*%4.2f*\n", RENT); printf("*%3.1f*\n", RENT); printf("*%10.3f*\n", RENT); printf("*%10.3E*\n", RENT); printf("*%+4.2f*\n", RENT); printf("*%010.2f*\n", RENT); return 0; }
该程序的输出如下:
*3852.990000* // 默认设置 字段宽度是容纳带打印数字所需的位数和小数点后打印 6 位数字
*3.852990e+03* // 在小数点的左侧打印 1 个数字,在小数点的右侧打印 6 个数字
*3852.99*
*3853.0* // 四舍五入
* 3852.990*
* 3.853E+03* // 四舍五入 用 E 代替了 e
*+3852.99* // 转换说明中包含了 + 标记
*0003852.99* // 0 标记使得打印的值前面以 0 填充以满足字段要求
// 转换说明 %010.2f 的第1个0是标记,句点(.)之前、标记之后的数字(本例为10)是指定的字段宽度。
#include <stdio.h> int main() { printf("%x %X %#x\n", 31, 31, 31); printf("**%d**% d**% d**\n", 42, 42, -42); printf("**%5d**%5.3d**%05d**%05.3d**\n", 6, 6, 6, 6); return 0; }
该程序的输出如下:
1f 1F 0x1f // 1f 是十六进制数 等于十进制数 31
// 第1行printf()语句中 根据 %x 打印出1f %F 打印出 1F %#x打印出 0x1f
**42** 42**-42** // 负值前面不产生前导空格
** 6** 006**00006** 006** // 如果 0 标记和精度一起出现,0 标记会被忽略
#include <stdio.h> #define BLURB "Authentic imitation!" int main() { printf("[%2s]\n", BLURB); printf("[%24s]\n", BLURB); printf("[%24.5s]\n", BLURB); printf("[%-24.5s]\n", BLURB); return 0; }
该程序的输出如下:
[Authentic imitation!]
[ Authentic imitation!]
[ Authe] // .5告诉 printf() 只打印 5 个字符
[ Authe ]
四、使用scanf()函数
如果用 scanf() 读取基本变量类型的值,在变量名前加上一个 & ;
如果用 scanf() 把字符串读入字符数组中,不要使用 & 。
scanf() 函数使用空白(换行符、制表符和空格)把输入分成多个字段。在依次把转换说明和字段匹配时跳过空白。
唯一例外的是 %c 转换说明。根据 %c , scanf() 会读取每个字符,包括空白。
scanf() 的转换说明:
scanf()转换说明中的修饰符 :
1.从scanf()角度看输入
scanf() 函数每次读取一个字符,跳过所有的空白字符,直至遇到第1 个非空白字符才开始读取。
如果使用 %s 转换说明, scanf() 会读取除空白以外的所有字符。scanf() 跳过空白开始读取第 1 个非空白字符,并保存非空白字符直到再次遇到空白。
C 语言还有其他的输入函数, 如 getchar() 和 fgets() 。这两个函数更适合处理一些特殊情况,如读取单个字符或包含空格的字符串。后面将会详细介绍。
2.格式字符串中的普通字符
scanf() 函数允许把普通字符放在格式字符串中。除空格字符外的普通字符必须与输入字符串严格匹配。
例如,假设在两个转换说明中添加一个逗号:
scanf("%d,%d", &n, &m);
scanf() 函数将其解释成:用户将输入一个数字、一个逗号,然后再输入一个数字。也就是说,用户必须像下面这样进行输入两个整数:
88,121
由于格式字符串中,%d 后面紧跟逗号,所以必须在输入 88 后再输入一个逗号。但是,由于scanf() 会跳过整数前面的空白,所以下面两种输入方式都可以:
88, 121
和
88,
121
格式字符串中的空白意味着跳过下一个输入项前面的所有空白。例如,对于下面的语句:
scanf("%d ,%d", &n, &m);
以下的输入格式都没问题:
88,121
88 ,121
88 , 121
请注意, “所有空白” 的概念包括没有空格的特殊情况。
除了 %c ,其他转换说明都会自动跳过待输入值前面所有的空白。
因此,scanf("%d%d", &n, &m) 与 scanf("%d %d", &n, &m) 的行为相同。对于 %c ,在格式字符串中添加一个空格字符会有所不同。例如,如果把 %c 放在格式字符串中的空格前面, scanf() 便会跳过空格,从第 1 个非 空白字符开始读取。也就是说, scanf("%c", &ch) 从输入中的第 1 个字符开始读取,而 scanf(" %c", &ch) 则从第 1 个非空白字符开始读取。
3.scanf()的返回值
scanf() 函数返回成功读取的项数。如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,scanf() 便返回 0 。当 scanf() 检测到 “ 文件结尾 ” 时,会返回 EOF ( EOF 是 stdio.h 中定义的特殊值,通常用 #define 指令把 EOF 定义为 -1 )。
五、printf() 的用法提示
想把数据打印成列,指定固定字段宽度很有用。
在两个转换说明中间插入一个空白字符,可以确保即使一个数字溢出了自己的字段,下一个数字也不会紧跟该数字一起输出(这样两个数字看起来像是一个数字)。这是因为格式字符串中的普通字符(包括空格)会被打印出来。