跳转至

第三章 格式化输入输出

scanf 函数和 printf 函数是C语言使用最频繁的两个函数,它们用来支持格式化的读和写。


printf 函数

printf 函数被设计用来显示格式串( format string )的内容,并且在字符串指定位置插入可能的值。

printf(格式串, 表达式1, 表达式2, ...);

格式串包含普通字符和转换说明( conversion specification ),其中转换说明以字符%开头。

Warning

C语言编译器不会检测格式串中转换说明的数量是否和输出项的数量相匹配。

转换说明

在通用的情况下,转换说明可以有%m.pX格式或%-m.pX格式,这里的m和p都是整型常量,X是字母。m和p都是可选项。

在转换说明%10.2f中,m是10,p是2,X是f。

最小字段宽度( minimum field width ) m指定了要显示的最小字符数量。如果要打印的数值比m个字符少,那么值在字段内是右对齐的。如果要多,那么字段宽度会自动扩展为需要的尺寸。

精度( precision ) p的含义依赖于转换说明符X( conversion specifier )的选择。对数来说,最常用的转换说明符有:

  • d,表示十进制形式的整数。p说明可以显示的数字的最少个数(如果需要,就在数前加上额外的零);如果忽略掉p,默认它的值为1。

  • e,表示指数形式的浮点数。p说明小数点后应该出现的数字的个数(默认为6)。如果p为0,则不显示小数点。

  • f,表示“定点十进制”形式的浮点数,没有指数。p的含义与在说明符e中的一员。

  • g,表示指数形式或者定点十进制形式的浮点数,形式的选择根据数的大小决定。p可以说明显示的有效数字的最大数量。与转换说明符f不同,g的转换将不显示尾随零。

转义序列

我们经常把在格式串中用的代码\n称为转义序列( escape sequence )。转义序列使字符串包含一些特殊字符而又不会使编译器引发问题。

详细的说明:https://zh.cppreference.com/w/cpp/language/escape

scanf 函数

scanf 函数也根据特定的格式读取输入, scanf 函数转换说明符的用法和 printf 函数转换说明符的用法本质上是一样的。

scanf 函数有一些不易察觉的陷阱。使用 scanf 时,程序员必须检查转换说明的数量是否与输入变量的数量相匹配,并且检查每个转换是否适合相对应的变量。另一个陷阱涉及符号&,通常把符号&放在 scanf 函数调用的每个变量的前面。

调用 scanf 函数是读取数据的一种有效但不理想的方法。许多专业C程序员避免用 scanf 函数,而是采用字符格式读取所有数据,然后再把它们转换成数值形式。

scanf 函数的工作方法

scanf 函数本质上是一种“模式匹配”函数,也就是试图把输入的字符组与转换说明匹配成组。

scanf 调用时,从左边开始处理字符串中的信息。对于格式串中的每一个转换说明, scanf 函数努力从输入的数据中定位适当类型的项,并且跳过必要的空格。然后, scanf 函数读入数据项,并且在遇到不可能属于此项的字符时停止。

在寻找数的起始位置时, scanf 函数会忽略空白( white-space )字符(空格符、横向和纵向制表符、换页符、换行符)。

格式串中的普通字符

处理格式串中普通字符时, scanf 函数采取的动作依赖于这个字符是否为空白字符。

  • 空白字符。当在格式串中遇到一个或多个连续的空白字符时, scanf 函数从输入中重复读空白字符直到遇到一个非空白字符(把该字符“放回原处”)为止。

  • 其他字符。当在格式串中遇到一个非空白字符时, scanf 函数将把它与下一个输入字符进行比较。如果两个字符相匹配,那么 scanf 函数会放弃输入字符而继续处理格式串。如果两个字符不匹配,那么 scanf 函数会把不匹配的字符放回输入中,然后异常退出。