scanf返回值是什么(C语言之妙:scanf 的双重作用)


我们尝试用scanf做累加运算:

/* summing.c -- sums integers entered interactively */ #include <stdio.h> int main(void) { long num; long sum = 0L; /* initialize sum to zero */ int status; printf("Please enter an integer to be summed "); printf("(q to quit): "); status = scanf("%ld", &num); while (status == 1) /* == means "is equal to" */ { sum = sum + num; printf("Please enter next integer (q to quit): "); status = scanf("%ld", &num); } printf("nThose integers sum to %ld.n", sum); return 0; }

该程序使用long类型以存储更大的整数。尽管C编译器会把0自动转换为合适的类型,但是为了保持程序的一致性,我们把sum初始化为0L(long类型的0),而不是0(int类型的0)。该程序的运行示例如下:

Please enter an integer to be summed (q to quit): 44

Please enter next integer (q to quit): 33

scanf返回值

Please enter next integer (q to quit): 88

Please enter next integer (q to quit): 121

Please enter next integer (q to quit): q

Those integers sum to 286.

分布解析

先看while循环,该循环的测试条件是如下表达式:

status == 1

运算符是C的相等运算符(equality-operator),该表达式判断status是否等于1。不要把status == 1 与 status = 1混淆,后者是把1赋给status。根据测试条件status == 1,只要status等于1,循环就会重复。每次循环,num的当前值都被加到sum上,这样sum的值始终是当前整数之和。当status的值不为1时,循环结束。然后程序打印sum的最终值。

要让程序正常运行,每次循环都要获取num的一个新值,并重置status。程序利用scanf()的两个不同的特性来完成。首先,使用scanf()读取num的一个新值;然后,检查scanf()的返回值判断是否成功获取值。第4章中介绍过,scanf()返回成功读取项的数量。如果scanf()成功读取一个整数,就把该数存入num并返回1,随后返回值将被赋给status(注意,用户输入的值存储在num中,不是status中)。

这样做同时更新了num和status的值,while循环进入下一次迭代。如果用户输入的不是数字(如,q),scanf()会读取失败并返回0。此时,status的值就是0,循环结束。因为输入的字符q不是数字,所以它会被放回输入队列中(实际上,不仅仅是q,任何非数值的数据都会导致循环终止,但是提示用户输入q退出程序比提示用户输入一个非数字字符要简单)。

如果scanf()在转换值之前出了问题(例如,检测到文件结尾或遇到硬件问题),会返回一个特殊值EOF(其值通常被定义为-1)。这个值也会引起循环终止。如何告诉循环何时停止?该程序利用scanf()的双重特性避免了在循环中交互输入时的这个棘手的问题。例如,假设scanf()没有返回值,那么每次循环只会改变num的值。虽然可以使用num的值来结束循环,比如把num > 0(num大于0)或num != 0(num不等于0)作为测试条件,但是这样用户就不能输入某些值,如-3或0。也可以在循环中添加代码,例如每次循环时询问用户“是否继续循环?<y/n>”,然后判断用户是否输入y。这个方法有些笨拙,而且还减慢了输入的速度。使用scanf()的返回值,轻松地避免了这些问题。

伪码

现在,我们来看看该程序的结构。总结如下:

initialize sum to 0 prompt user read input while the input is an integer, add the input to sum, prompt user, then read next input after input completes, print sum

顺带一提,这叫作伪代码(pseudocode),是一种用简单的句子表示程序思路的方法,它与计算机语言的形式相对应。伪代码有助于设计程序的逻辑。确定程序的逻辑无误之后,再把伪代码翻译成实际的编程代码。使用伪代码的好处之一是,可以把注意力集中在程序的组织和逻辑上,不用在设计程序时还要分心如何用编程语言来表达自己的想法。例如,可以用缩进来代表一块代码,不用考虑C的语法要用花括号把这部分代码括起来。

总之,因为while循环是入口条件循环,程序在进入循环体之前必须获取输入的数据并检查status的值,所以在while前面要有一个scanf()。要让循环继续执行,在循环内需要一个读取数据的语句,这样程序才能获取下一个status的值,所以在while循环末尾还要有一个scanf(),它为下一次迭代做好了准备。可以把下面的伪代码作为while循环的标准格式:

get first value to be tested while the test is successful process value get next valueC 风格读取循环

根据伪代码的设计思路,程序清单6.1可以用Pascal、BASIC或FORTRAN来编写。但是C更为简洁,下面的代码:

status = scanf("%ld", &num); while (status == 1) { /* loop actions */ status = scanf("%ld", &num); } // can be replaced by the following: while (scanf("%ld", &num) == 1) { /* loop actions */ }

第二种形式同时使用scanf()的两种不同的特性。

首先,如果函数调用成功,scanf()会把一个值存入num。

然后,利用scanf()的返回值(0或1,不是num的值)控制while循环。

因为每次迭代都会判断循环的条件,所以每次迭代都要调用scanf()读取新的num值来做判断。换句话说,C的语法特性让你可以用下面的精简版本替换标准版本。

您可以还会对下面的文章感兴趣

最新评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

使用微信扫描二维码后

点击右上角发送给好友