在练习一道基础题输入未知个数进行求和、求平均数练习时,使用了scanf和getchar的联用。中间产生的问题进行探讨。先贴上具体代码:
#include <stdio.h>
int main()
{
int n = 0;
int x = 0;
int i = 0;
int min = 0;
int max = 0;
float av_value = 0;
char keyWord;//添加循环判断条件,如果输入回车键,输入结束。
while( scanf("%d",&n),keyWord=getchar())
{
if(n>1000)
{
printf("%d大于1000不计入数据里面\n",n);
continue;
}
x = x + n;
if(i == 0)
{
max = n;
min = n;
}
i++;
if (n > max) max = n;
if (n < min) min = n;
//putchar(keyWord);
if(keyWord=='\n')
{
break;
}
}
av_value = (float) x / i;
printf("%d %d %.3f\n",min,max, av_value );
return 0;
}
第一个问题是为什么不将控制条件语句改成这样 while( scanf("%d",&n),getchar()!='\n')?
最开始做这道题时,因为理解很浅,我就以上面这种方式来作为控制条件,虽然也能成功跳出循环,但是有一个问题,就是最后一个数字是不能成功参与运算。
在这种情况下就需要挖掘下scanf("%d",&n)和getchar()是怎样工作的。
当输入一串字符:1,2,3,4,5回车 时两个函数是交替从标准输入流缓冲区中读取数据
第一次:scanf读取到数据就是“1”,getchar读取到数据是“,”。
第二次:scanf读取到数据就是“2”,getchar读取到数据是“,”。
以此类推,最后scanf读取到5,getchar读取到回车‘\n’,于是程序结束,循环体内的逻辑运算并没有执行。
在这里还需要说明的是标准输入流缓冲区和键盘缓冲区是两块不同的缓冲区,getch()从键盘缓冲区读取数据,代表着即时性,键盘敲击一个按键,getch()就能即时读取到。按下回车后,键盘缓冲区的数据才转移到流缓冲区。也就是当输入上面一串字符时,getchar和scanf并不会立即读取到数据,直到按下回车键后,scanf才从流缓冲区中读取第一个数据1,不断循环直到读取到最后一个回车键字符‘\n’。
第二个问题在·修改成正确的代码之后,我发现如果输入1,2,3,4,5 回车,在输入5之后再增加一个或者任意个空格键就会导致回车无法生效。按照最初的想法,scanf和getchar交替读取字符,那么在5之后添加两个空格键后再回车应该是有效的,但是结论是无效的。这里就需要考虑到一个问题,scanf("%d",&n)是会忽略任何空格字符的包括回车‘\n’和tab'\t'。所以必须输入一个非空字符再输入回车才有效。如果是scanf("%c",&n)就不会忽略空格字符。
以上。