最近做题发现键入回车后,总会产生一些意料之外的结果……并未完全达到预期的目标,今日偶的解法,隧简单分析一波。
先从一个简单的小程序开始,我们先忽略它糟糕的算法:
/*guess.c--一个糟糕且错误的猜数字程序
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int i=1;
printf("Think a number in your mind,I will guess it.\n");
printf("Input a y if I'm right and an n if I am wrong\n");
while (getchar() != 'y')//读取字符,与y做对比
printf("The number is %d, right?\n", i++);
system("pause");
return 0;
}
我在心中默想一个数,通过键入
或者
,告诉程序,它的猜测是否正确。我们可以注意到,每次输入
,程序打印两条消息;直接输入回车,也会打印一条消息。这是因为程序将
当作我否定数字
,将
当作我否定了数字
。
要解决这个问题,我们要了解程序是如何使用用户输入的字符的。我们输入的字符被收集并储存在一个称为缓冲区的临时储存区,按下
后,程序才能使用我们输入的字符,直到缓冲区内的字符全都被读取完,如下图:
这里我们只讨论缓冲输入,对于非缓冲输入不会遇到这样的问题,故不做赘述。知道了问题的关键,我们可以设计一个
循环来丢弃输入行剩余的内容,包括换行符。
while (getchar() != 'y')
{
printf("The number is %d, right?\n", i++);
while (getchar() != '\n')
continue;//跳过剩余输入行
}
这相当于把字符从缓存区取出后,执行一段空语句。
将一直读取,一直丢弃,直到清空缓存区。使用上述循环后,程序输出如下:
这体现出,每使用一次 只能读取当前字符的后一个字符, 本身并不能存储,若要比较某个位置的字符与特定字符的关系,则应及时赋值变量,储存响应。
/*guess-1.c--另一个糟糕且错误的猜数字程序
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int i = 50, upper = 100, lower = 0;
printf("50?\n");
while (getchar()!= 'y') //输入char-1 '\n'。其中char-1被取出,此时缓存区中:'\n'。
{
printf("Tell me big or small:\n");
while (getchar() != '\n') //此时缓存区被清空
continue;
if (getchar() == 'a') //输入char-2 '\n'。其中char-2被取出与'a'进行比较,此时缓存区中:'\n'。
{
i = 1;
printf("%d?", i);
while (getchar() != '\n')
continue;
}
if (getchar() == 'b') //缓存区中的'\n'被取出与'b'进行比较。
{
i = 2;
printf("%d?", i);
while (getchar() != '\n')
continue;
}
}
system("pause");
return 0;
}
我们想做到输入 时,执行一段代码,输入 时执行另一段,但是事与愿违。这是由于没有理解每次调用 ,都会向后读取缓冲区一格的内容。可做如下修改,
char ch;
ch=getchar(); //及时赋值变量以储存响应。
if (ch == 'a')
{
i = 1;
printf("%d?", i);
while (getchar() != '\n')
continue;
}
if (ch == 'b')
{
i = 2;
printf("%d?", i);
while (getchar() != '\n')
continue;
}
再次强调: 本身并不能存储,若要比较某个位置的字符与特定字符的关系,则应及时赋值变量,储存响应。