关于缓冲区和getchar的理解咱们先来看一串代码。
int main()
{
printf("请输入密码:>");
char password[20] = { 0 };
scanf("%s", password);
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
可以先自行理解一下这串代码看看能不能完成确认密码这一个步骤。
可以看到正常运行下来到确认密码这一步它会直接进行确认失败,说明前面的getchar已经读取到字符,可是我并没有输入任何东西,它是从哪里读取到的字符呢?
这里就要引入一个新的知识——缓冲区了。
如图所示,当我们敲代码中使用的有关输入的函数,比如getchar,scanf等等。都是从输入缓冲区中读取的,并不是说从键盘输入中直接读取数据,具体流程是键盘输入的数据放到输入缓冲区中,然后getchar,scanf等输入函数从输入缓冲区里面读取数据。
了解到这里你可能还不能完全了解上述问题,还要知道每当你输入完数据之后按得回车也会被存到输入缓冲区里。也就是\n。
了解到这个,咱们再回到刚才那个问题是不是就明朗很多啦。在你输入完A之后,A被scanf读取到了,而\0还留在输入缓冲区当中,在你进行下一步int ch = getchar();的时候,getchar就在缓冲区读到了你的\0,然后就去进行判断了。结果显而易见。
这里可能有有点疑惑了,为什么scanf不会读取这个\0,而getchar读取到这个\0。自己以前敲代码用多个scanf函数的时候也不会出现这个问题啊。
这里咱们就先了解一下getchar具体是怎样运行的,它的语法是怎样的。
getchar的用途是读取一个字符,getchar 读取到字符的时候返回的是字符的ASCII码值。如果读取失败,返回的是EOF ---> -1 (ASCII:0~127)
这里可以知道为什么getchar能读取到\0,而且这个\0还能被int ch给接收了。
那么我们该如何改才能成功运行呢。很简单既然多了一个字符,那我也多一个getchar去接收它就好了。如图:
这样就可以实现这个代码的正确功能了。但是还没完,在看看下面这份代码的运行结果。
这怎么又直接“确认失败”了呢。
这里面输入密码的时候多了一个空格,而空格scanf不接收,这里面scanf只接收到了1234,剩下的都只能在输入缓冲区里待着,然后就被下面的getchar给接收到了。
那有没有什么办法可以一劳永逸的呢,直接把输入缓存区里的数据全部清空,不影响下一次的接收呢。
其实是有的,我们只需要用一个循环语句就可以实现了。
可以看到我们的运行结果正常了,用循环语句,判断getchar接收到的数据是否为\0,因为你最后一个数据肯定是\0,回车肯定是最后一个嘛。所以当你接收到这个数据的时候,说明你的输入缓存区肯定是空的了。
那么scanf有没有办法读取到空格呢,当然是有的。
如图我们实现了scanf读取空格,用到了[^\n],这个的意思是一直读取数据直到遇到\n。这样就可以实现接收空格了。