读书笔记系列之《C语言程序设计现代方法》----第三章

x33g5p2x  于2022-02-24 转载在 其他  
字(2.7k)|赞(0)|评价(0)|浏览(115)

第三章 格式化输入

3.1 printf函数

printf函数被用来显示格式串的内容,并且在该串中的指定位置插入可能的值。

注意:跟随在字符%后的信息指定了把数值从内部形式(二进制)转换成打印形式(字符)的方法。

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

下面这个printf函数调用所拥有的转换说明的数量就多于要显示的值的数量:

printf("%d %d\n",i);

printf函数将正确显示变量i的值,接着显示另一个(无意义的)整数值。函数调用带有太少的转换说明也会出现类似的问题:

printf("%d\n",i,j);

在这种情况下,printf函数会显示变量i的值,但是不会显示变量j的值。

此外,C语言编译器也不检测转换说明时候适合要显示项的数据类型。如果程序员使用不正确的转换说明,程序将会简单产生无意义的输出。

3.1.1转换说明

一般,转换说明可以用==%m.pX格式或%-m.pX==格式,这里的m和p都是整数常量,而X是字母。m和p都是可选的,如果省略掉p,m和p之间的小数点也要去掉。

  • m:最小字段宽度,如果要显示的数值所需的字符数少于m,那么值在字段内是右对齐的。(换句话说,在值前面放置额外的空格。)如果要显示的值所需的字符数
    多余m,那么字符宽度会自动扩展为所需的尺寸。

  • -:由默认的右对齐方式变为左对齐。

精度p的含义很难描述,因为它依赖于转换说明符X的选择。X表明在显示数值前需要对其进行哪种转换。对数值来说最常用的转换说明符有以下几个。

  • d:表示十进制(基数为10)形式的整数。p指明了待显示的是数字的最少个数(必要时在数字前加上额外的零);如果省略p,就默认它的值为1.
  • e:表示指数(科学计数法)形式的浮点数。p指明了小数后应该出现的数字的个数(默认值为6),如果p为0,则不显示小数点。
  • f:p的含义与e一样。
  • g:表示指数形式或者定点十进制形式的浮点数,形式的选择根据数的大小决定。p说明可以显示的有效数字(没有小数点后的数字)的最大数量。与转换说明符f不同,g的转换将不显示尾随的0(例如5.50显示5.5,5.0显示5)。此外,如果要显示的数值没有小数点后的数字,g就不会显示小数点。

注意:在用于显示大小适中的数时,说明符g采用定点十进制形式。但是,在显示非常大或者非常小的数时,说明符g就会转换成指数形式以便减少所需的字符数。

3.2 scanf函数

3.2.1 scanf函数的工作方法

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

像printf函数一样,scanf函数是由格式串控制的。调用时,scanf函数从左边开始处理字符串中的信息,对于格式串中的每一个转换说明,scanf函数从输入的数据中定位适当类型的项,并在必要时跳过空格。然后,scanf函数读入数据项,并且在遇到不可能属于此项的字符时停止。如果读入数据项成功,那么scanf函数会继续处理格式串的剩余部分;如果某一项不能成功读入,那么scanf函数将不再查看格式串的剩余部分(或者余下的输入数据)而立即返回。

在寻找数的起始位置时,scanf函数会忽略空白字符,包括空格符、水平和垂直制表符、换页符和换行符。

转换说明%e、%f和%g时可以互换的,这三种转换说明在识别浮点数方面都遵循相同的规则。

3.2.2格式串中的普通字符

空白字符:

格式串中的一个空白字符可以与输入中任意数量的空白字符相匹配。(包含零个)

注意:在格式串中包含空白字符并不意味着输入中必须包含空白字符。

其它字符:

如果两个字符相匹配,那么scanf函数会放弃输入字符而继续处理格式串。如果两个字符不匹配,那么scanf函数会把不匹配的字符放回输入中,然后异常退出,而不仅进一步处理格式串或者从输入中读取字符。

举例:

假设格式串是"%d/%d"(*代表空格)

如果输入是*5/*96
在寻找整数时,scanf函数会跳过第一个字符,把%d与5相匹配,把/和/相匹配,在寻找下一个整数时跳过一个空格,并且把%d与96相匹配。

另一方面,如果输入是

*5*/*96
scanf函数会跳过一个空格,把%d与5相匹配,然后试图把格式串中的/与输入的空格相匹配。但是二者不匹配,所以scanf函数把空格放回原处,把字符*/*96留给下一次scanf函数调用来读取。为了允许第一个数后边有空格,应使用格式串"%d
/%d"。

3.3.3 易混淆的printf和scanf函数

scanf("%d,%d",&i,&j);
scanf函数首先寻找输入中的函数,把这个整数存入变量中,把这个整数存入变量i中;然后,scanf函数将试图把逗号与下一个输入字符相匹配。如果下一个输入的字符是空格而不是逗号,那么scanf函数将终止操作,而不再读取变量j的值。

注意:printf格式串经常以\n结尾,但是在scanf格式串末尾放置换行符通常是一个怀主意。对scanf函数来说,格式串中的换行符等价于空格,两者都会引发scanf函数提前进入到一个非空白字符。例如,如果格式串是"%d\n",那么scanf函数将跳过空白字符,读取一个整数,然后跳到下一个非空白字符处。像这样的格式串可能会导致交互式程序一直"挂起"直到用户输入一个非空白字符为止。

问与答

  1. 问:转换说明%i也可以用于读写整数。%i和%d之间有什么区别?

答:在printf格式串中使用时二者没有区别。但是,在scanf格式串中%d只能与十进制(基数为10)形式的整数相匹配,而%i可以匹配用八进制、十进制或十六进制表示的整数。如果输入的数有前缀0,难么%i会把它作为八进制数来处理;如果输入的数有前缀0x或0X,那么%i会把它作为十六进制数来处理。如果用户意外的将0放在数的开始处,那么用%i代替%d读取数可能会有意想不到的结果。由于这是一个陷阱。所以建议坚持采用%d。

  1. 问:如果printf函数将%作为转换说明的开始,那么如何显示字符%呢?

答:如果printf函数在格式串中遇到两个连续的字符%,那么它将显示出一个%。

  1. 问:转义序列\t会使printf函数跳到下一个水平制表符处。如何知道水平制表符能跳多远呢?

答:不可能知道。打印\t的效果不是由C语言定义的,而是依赖于所使用的操作系统。水平制表符之间的举例通常是8个字符宽度,但C语言本身无法保证这一点。

相关文章