购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

问与答

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

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

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

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

printf("Net profit: %d%%\n", profit);

可以显示出

Net profit: 10%

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

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

问:如果要求读入一个数,而用户录入了非数值的输入,那么 scanf 函数会如何处理?

答:请看下面的例子:

printf("Enter a number: ");
scanf("%d", &i);

假设用户录入了一个有效数,后边跟着一些非数值的字符:

Enter a number: 23foo

这种情况下, scanf 函数读取 2 3 ,并且将23存储在变量 i 中,而剩下的字符( foo )则留给下一次 scanf 函数调用(或者某些其他的输入函数)来读取。另外,假设输入从开始就是无效的:

Enter a number: foo

这种情况下,没有值会被存储到变量 i 中,字符 foo 会留给下一次 scanf 函数调用。

如何处理这种糟糕的情况呢?后面将看到检测 scanf 函数调用是否成功(➤22.3节)的方法。如果调用失败,可以终止或者尝试恢复程序,可能的方法是丢掉有问题的输入并要求用户重新输入。(在第22章结尾的“问与答”部分会讨论有关丢弃错误输入的方法。)

问:我不能理解 scanf 函数如何把字符“放回原处”并在以后再次读取。(p.33)

答:我们知道,用户从键盘输入时,程序并没有读取输入,而是把用户的输入放在一个隐藏的缓冲区中,由 scanf 函数来读取。 scanf 函数把字符放回到缓冲区中供后续读取是非常容易的。第22章会更详细地讨论输入缓冲。

问:如果用户在两个数之间加入了标点符号(如逗号), scanf 函数将如何处理?

答:先来看一个简单的例子。假设我们想用 scanf 函数读取一对整数:

printf("Enter two numbers: ");
scanf("%d%d", &i, &j);

如果用户输入

4,28

scanf 函数将读取4并且把它存储在变量 i 中。在寻找第二个数的起始位置时, scanf 函数遇到了逗号。因为数不能以逗号开头,所以 scanf 函数立刻返回,而把逗号和第二个数留给下一次 scanf 函数调用。

当然,如果能确定数与数之间 始终 用逗号来分隔,我们可以很容易地解决这个问题,只要在格式串中添加逗号即可: JhhJdgPz1uzZhmvw0FPZ92fNEachqJXU0h2baoV+SKFSyuH9WiMPutOjquCUrTDW

printf("Enter two numbers, separated by a comma: ");
scanf("%d,%d", &i, &j);
点击中间区域
呼出菜单
上一章
目录
下一章
×