C03-格式化输入输出
在探索难以实现的问题时,问题本省的简单性只会使情况更糟
1.printf 函数
printf函数
被设计用来显示格式串(format string)
的内容,并且在该串中的指定位置插入可能的值。调用printf函数时必须提供格式串,格式串后面的参数是需要在显示时插入到该串中的值。
显示的值可以是常量
、变量
或者更加复杂的表达式
。调用printf函数
一次可以打印的值的个数没有限制。
printf("格式串,表达式1,表达式2,...");
格式串
包含普通字符
和转换说明(conversion specification)
,其中转换说明以字符%
开头。转换说明是用来表示打印过程中待填充的值的占位符
。
跟随在字符%
后边的信息指定了把数值从内部形式(二进制)
转换成打印形式(字符)
的方法,这也就是“转换说明”这一术语的由来。例如,转换说明%d
指定printf函数
把int型
值从二进制形式转换成十进制数字组成的字符串,转换说明%f
对float型
值也进行类似的转换。
int i = 10;
int j = 20;
float x = 43.28f;
float y = 55.0f;
printf("i=%d, j=%d, x=%f, y=%f", i, j, x, y);
1.1 转换说明
转换说明符
给程序员提供了大量对输出格式的控制方法,%d与%f是最简单的转换说明,而转换说明具有复杂的展示形式。
格式化输入输出的转义字符完整的表达式为%m.pX
m
m
可以指定最小字段宽度(minimum filed width)
,如果指定的最小宽度小于要显示的字符数时,则原有的字符不会被隐藏;如果指定的最小宽度大于要显示的字符数时,则会在字符串前添加相应空格。
m为正数
时,字符右对齐(默认);m为负数
时,字符左对齐。
p
精度p(precision)
的含义依赖于转换说明符(conversion specifter)X
的选择。X表明在显示数值前需要对齐进行哪种转换。常用的转换说明符有:
d
:表示十进制形式的证书,p
指明了待显示的数字的最少个数。默认为1
e
:表示指数形式
的浮点数,p
指明了小数点后应该出现的数字个数。默认为6
,如果p
为0
则不显示小数点f
:表示定点十进制
形式的浮点数,没有指数。P
的作用与e
相同g
:表示指数
形式或者定点十进制
形式的浮点数
,形式的选择根据数的大小
决定。在显示大小适中的数值时,会采用定点十进制的形式,若是显示非常大或者非常小的数字时,会采用指数形式以减少所需要的字符数
%d %e %f %g
%5d %-5d %5.3d
%10.3f %10.3e %-10g
1.2 转义序列
格式串中常用的代码\n
被称为转义序列(escpae sequence)。转义序列使字符串包含一些特殊字符而不会使编译器引发问题,这些字符包括非打印的字符和对编译有特殊含义的字符
转义序列 | 含义 |
---|---|
\ | \字符 |
' | ' 字符 |
" | " 字符 |
? | ? 字符 |
\a | 警报铃声 |
\b | 退格键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
2.scanf 函数
scanf函数
也根据特定的格式读取输入。相printf函数
格式串一样,scanf
函数的格式串也可以包含普通字符和转换说明两部分。
调用scanf函数
是读数据的一种有效但不理想的方法。我们应该避免使用scanf函数,而是采用字符格式
读取所有数据,然后再把他们转换成数值形式
。
scanf("%d%d%f%f",&i,&j,&x,&y);
// 输入:1 -20 .3 -4.e3
// 使 i=1, j=-20, x=0.3, y=-4.0e3
// 注意输入时的空格
2.1 scanf 函数的工作方法
scanf函数
本质是是一种模式匹配
函数,试图把输入的字符组与转换说明相匹配。
调用scanf函数
时, scanf函数从左边开始处理字符串中的信息。对于格式串中的每一个转换说明,scanf函数从输入的数据中定位适当类型的项,并在必要时跳过空格。
然后,scanf函数读入数据项,并且在遇到不可能属于此项的字符时停止。如果读入数据项成功
,那么scanf函数会继续处理格式串的剩余部分;如果某一项不能成功
读入,那么scanf 函数将不再查看格式串的剩余部分(或者余下的输入数据)而立即返回。
在寻找数的起始位置时,scanf函数
会忽略空白字符 (white-space character,包括空格符
、 水平制表符
和垂直制表符
、换页符
和换行符
)。因此,我们可以把数字放在同一行或者分散在几行内输 入。
scanf("%d%d%f%f",&i,&j,&x,&y);
// 将输入分为三行
/*
1
-20
.3 -4.0e3
*/
// 使 i=1, j=-20, x=0.3, y=-4.0e3
scanf函数
会把多行的输入看成是一个连续的字符流
。
当scanf函数
遇到一个不可能属于当前项的字符时,它会把此字符放回原处
,以便 在扫描下一个输入项或者下一次调用scanf函数
时再次读入。可以尝试运行下列代码
![[C语言代码块#循环输入]]
2.2 格式串中的普通字符
空白字符
当在格式串中遇到一个或多个连续的空白字符
时, scanf函数从输入中重复读空白字符
直到遇到一个非空白字符
(把该字符“放回原处”)为止。格式串中空白字符
的数量无关紧要,格式串中的一个空白字符可以与输入中任意数量的空白字符相匹配(包括零个),并且在格式串中包含空白字符并不意味着输入中必须包含空白字符。
其它字符
当在格式串中遇到非空白字符
时,scanf函数将把它与下一个输入字符进行比较。如果两个字符相匹配,那么scanf函数会放弃输入字符而继续处理格式串。如果两个字符不匹配,那么scanf函数会把不匹配的字符放回输入中,然后异常退出,而不进一步处理格式串或者从输入中读取字符。
例如,scanf("请输入:%d", &i);
中,运行时,需要先输入字符串“请输入:”,然后才开始输入转换说明
.
2.3 printf函数和scanf函数中的注意事项
- printf函数中,变量前不需要添加字符
&
- printf函数建议使用转义字符
\n
结尾 - printf函数中如果要打印
%
,要连续使用两个百分号%%
- scanf函数会在寻找数据项时跳过空白字符,所以除了转换说明,格式串常常不需要包含字符