/*
*作者: rookie_wei
*
*
*说明:下面讨论一下在c语言中使用scanf和getchar从键盘中获取字符串出现的问题,
* 这些问题很隐蔽,有时很难发现。希望能帮到你们。如果有什么理解错误之处,还请高手们指出。
*
*日期:2012.7.29
*/
例如代码:
int main(void)
{
int a, b, c, max;
char ch;
do
{
printf("Please input a, b and c: \n");
scanf("%d%d%d", &a, &b, &c);
max = a > b ? a : b;
max = max > c ? max : c;
printf("Max = %d\n", max);
printf("Y/y continue\n");
ch = getchar();
while((getchar()) != '\n');
putchar(ch);
}while(ch == 'y' || ch == 'Y');
return 0;
}
运行结果:
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$ ./1
Please input a, b and c:
1 2 3
Max = 3
Y/y continue
y
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$
其运行结果是即使最后输入键盘的是y/Y但是仍然不能进入循环。
分析问题的原因:
scanf的工作过程是将按键值存入输入缓冲区,然后直接读取输入缓冲区的内容,scanf遇到回车(\n)才结束
在上面的例子中,我们在键盘上输入的实际值是:
a\0b\0c\n 注:\0表示空格 \n表示回车
所以存在输入缓冲区的值是:a\0b\0c\n
scanf遇到回车(\n)而结束,scanf读取后输入缓冲区残留的内容就只剩下\n了,
所以下面的ch = getchar();语句在没有等到键盘输入时就已经读取了缓冲区的残留\n了,
因此即使键盘输入的是y/Y,但是ch获取的还是\n,这就解释了为什么当我们调用查看ch内容的
语句putchar(ch);时,结果输出的是换行而不是y。
由此可以猜测,scanf和getchar函数共用同一个输入缓冲区。
要解决此类问题的方法是,调用scanf函数后,将缓冲区里的残留清除掉,
做法是在scanf调用后使用while((getchar()) != '\n');语句清除残留。
将上面的代码改成
int main(void)
{
int a, b, c, max;
char ch;
do
{
printf("Please input a, b and c: \n");
scanf("%d%d%d", &a, &b, &c);
while((getchar()) != '\n');
max = a > b ? a : b;
max = max > c ? max : c;
printf("Max = %d\n", max);
printf("Y/y continue\n");
ch = getchar();
while((getchar()) != '\n');
putchar(ch);
}while(ch == 'y' || ch == 'Y');
return 0;
}
其输出结果是:
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$ ./1
Please input a, b and c:
1 2 3
Max = 3
Y/y continue
y
yPlease input a, b and c:
正是想要的结果。
*作者: rookie_wei
*
*
*说明:下面讨论一下在c语言中使用scanf和getchar从键盘中获取字符串出现的问题,
* 这些问题很隐蔽,有时很难发现。希望能帮到你们。如果有什么理解错误之处,还请高手们指出。
*
*日期:2012.7.29
*/
例如代码:
int main(void)
{
int a, b, c, max;
char ch;
do
{
printf("Please input a, b and c: \n");
scanf("%d%d%d", &a, &b, &c);
max = a > b ? a : b;
max = max > c ? max : c;
printf("Max = %d\n", max);
printf("Y/y continue\n");
ch = getchar();
while((getchar()) != '\n');
putchar(ch);
}while(ch == 'y' || ch == 'Y');
return 0;
}
运行结果:
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$ ./1
Please input a, b and c:
1 2 3
Max = 3
Y/y continue
y
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$
其运行结果是即使最后输入键盘的是y/Y但是仍然不能进入循环。
分析问题的原因:
scanf的工作过程是将按键值存入输入缓冲区,然后直接读取输入缓冲区的内容,scanf遇到回车(\n)才结束
在上面的例子中,我们在键盘上输入的实际值是:
a\0b\0c\n 注:\0表示空格 \n表示回车
所以存在输入缓冲区的值是:a\0b\0c\n
scanf遇到回车(\n)而结束,scanf读取后输入缓冲区残留的内容就只剩下\n了,
所以下面的ch = getchar();语句在没有等到键盘输入时就已经读取了缓冲区的残留\n了,
因此即使键盘输入的是y/Y,但是ch获取的还是\n,这就解释了为什么当我们调用查看ch内容的
语句putchar(ch);时,结果输出的是换行而不是y。
由此可以猜测,scanf和getchar函数共用同一个输入缓冲区。
要解决此类问题的方法是,调用scanf函数后,将缓冲区里的残留清除掉,
做法是在scanf调用后使用while((getchar()) != '\n');语句清除残留。
将上面的代码改成
int main(void)
{
int a, b, c, max;
char ch;
do
{
printf("Please input a, b and c: \n");
scanf("%d%d%d", &a, &b, &c);
while((getchar()) != '\n');
max = a > b ? a : b;
max = max > c ? max : c;
printf("Max = %d\n", max);
printf("Y/y continue\n");
ch = getchar();
while((getchar()) != '\n');
putchar(ch);
}while(ch == 'y' || ch == 'Y');
return 0;
}
其输出结果是:
rookiewei@ubuntu:~/classwork/c_test/sz_c_class/chapter5$ ./1
Please input a, b and c:
1 2 3
Max = 3
Y/y continue
y
yPlease input a, b and c:
正是想要的结果。