当前位置:网站首页>如何清空输入缓冲区
如何清空输入缓冲区
2022-04-22 07:50:00 【圣喵】

本期介绍
主要介绍了scanf()函数在读取输入数据时的一些特性,这些特性会导致的结果,还有应该如何解决输入缓冲区的滞留问题。
文章目录
前言
一般来说,我们写代码的时候经常会因为不清楚scanf()函数自身的一些特性,从而忽略输入缓冲区滞留的问题,这样必然会出现一系列连你自己都云里雾里的现象。所以及时的清空输入缓冲区,是有助于程序的健康发展的。那scanf()的特性有那些呢?如何有效的清空缓冲区呢?别着急,且听我娓娓道来。
scanf()函数的特性
今天我所讲只是关于scanf()函数在读取输入数据时的特性(主要讲读取字符串的部分),并不会深入的去剖析该函数。特性:
- scanf在被调用后会先检查缓冲区内是否有数据,若有则直接读取,否则就将会停滞,等待终端的输入。
- scanf只会读取它想要读的内容,余下的部分会滞留在缓冲区内。
- scanf在读取字符串时(即:“%s”时),若读到空白字符(空格、回车、水平制表Tab等等),scanf将停止读取。所以想要读取带空白字符的字符串scanf并不理想,应该用另一个函数gets()。
一个问题代码
下面串代码的目的是实现:设置一串字符密码,然后输入Y/S来确定。那么你说我在键盘上输入123456789然后回车,结果会是什么?
#include<stdio.h>
int main()
{
char ch = 0;
char ret = 0;
char password[20] = {
0 };
printf("设置密码:\n");//设置密码为:123456789
scanf("%s", &password);
printf("请确认:Y/S\n");
ret = getchar();
if (ret == 'Y')
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}

欸,怎么回事?我还没有输入Y/S呢,编译器怎么自己就判断并输出no了呢?好奇怪呀!导致如此的原因就是:没有考虑输入缓冲区,出现输入缓冲区堆积。那整个程序执行的过程是怎样的呢?问题出在哪个环节呢?

代码分析
问题主要出自scanf函数读取数据时并没有全部读取,还留了一部分在缓冲区内。为什么会读不干净呢?这就要讲到关于scanf函数的一个性质了,当程序执行到scanf("%s", &password);这时scanf会看一下输入缓冲区,若发现输入缓冲区内什么都没有,scanf就会等待(也就是我们执行代码时看见的光标一直在闪的原因)。

之后我们在键盘上输入123456789没按下回车时,键盘上输入的内容并没有被scanf所获取,而是存放在输入缓冲区内;只有当输入缓冲区检测到回车也就是‘\n’的存入,scanf或者getchar才会开始读取输入缓冲区的数据。

但就算你按下回车后scanf函数也不会如你所愿,把输入缓冲中的数据读的一干二净,它只会读它想读的数据,就像这里scanf只会读取:123456789,把‘\n’留在输入缓冲区内,然后被接下来的getchar读取存入ret当中,所以程序自然就会直接跳到输出:no了呀。

所以我们在scanf函数后加一段代码getchar(),读取滞留在缓存中的‘\n’,使得缓冲区清空。最终程序可以成功执行。
#include<stdio.h>
int main()
{
char ch = 0;
char ret = 0;
char password[20] = {
0 };
printf("设置密码:\n");//设置密码为:123456789
scanf("%s", &password);
getchar();//把那个回车给读取掉
printf("请确认:Y/S\n");
ret = getchar();
if (ret == 'Y')
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}

进一步分析
若我们使用上面那个被改正的代码, 然后在键盘上输入:abcdef hijk,程序结果会是什么呢?会成功执行吗?

事与愿违呢,似乎程序并不完善,为什么?因为我们还忽略了一个scanf的一个特性:scanf在读取字符串时(即:“%s”时),若读到空白字符(空格、回车、水平制表Tab等等),scanf将停止读取。

输入缓冲区中scanf只会读取abcdef,然后第一个getchar就只会读取那个空格,第二个getchar直接读取字符'h'并存入ret当中,程序自然就会直接跳到输出:no了呀。所以在scanf函数后加一段代码getchar()这种方法比较局限,它只能清空一个字符,无法处理掉所有剩余的部分,那该怎么办呢?我们发现啊不管你是如何输入,最后必然会敲回车键,那我们就写一个循环嘛,让getchar读读读,直到读取掉最后的那个‘\n’的时候停下来。加一段代码:while((ch=getchar())!='\n');。
#include<stdio.h>
int main()
{
char ch = 0;
char ret = 0;
char password[20] = {
0 };
printf("设置密码:\n");//设置密码为:abcdef hijk
scanf("%s", &password);
//清空缓冲区内所有滞留数据
while((ch=getchar())!='\n')
{
;
}
printf("请确认:Y/S\n");
ret = getchar();
if (ret == 'Y')
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}

总结
我们在学习一个库函数的时候,最好应该了解它的所有习性和特征,这样才能在以后的代码生涯中更好的去使用这些函数,不会调试最后出错了,查了N机遍还是一头雾水。

这份博客如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位点赞评论收藏️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧。
版权声明
本文为[圣喵]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_66769266/article/details/124151575
边栏推荐
- C language variable parameter usage
- navicat连接oracle数据库失败:cannot load OCI DLL,87:Instant Client package is ...
- The problems encountered in the compilation of Nacos source code are sorted out as follows
- 100. Same tree (easy)
- POI operation excel three swordsman
- Cesium collects terrain height and model height (asynchronous method, suitable for more data)
- 111. Minimum depth of binary tree
- 安卓开发——SQLite和SQLiteDatabase应用实验6笔记
- require-dev.mikey179/vfsStream is invalid, it should not contain uppercase characters. Please use m
- goto语句
猜你喜欢
随机推荐
HyperLedger Explorer 0.3.9环境搭建
C language variable parameter usage
Rhel7 - process management
How does CSDN reprint articles
win系统pinpoint编译安装遇到的坑和大家分享
Tissu hyperledger 1. 4 construction de l'environnement et essais d'échantillons
Sum method for varchar type in SQL (type error)
Realization of floor decomposition animation in cesium
布尔类型【bool】
@ data annotation in idea, get / set method does not work
14个py小游戏 源代码分享
重整笔记记录:【终极方法】在Vscode中用户创建自定义代码模板
Scanf / sprintf, fscanf / fprintf, sscanf / sprintf, snprintf of C language
Use of stream
解决磁盘有空间但创建不了文件---修复服务器文件系统
Client server communication project 2
DTV专业术语
素数求解的N种境界
POI操作excel三剑客
Rhel7 logical volume management - Notes









