Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >C语言缓冲区之 gets(str);fflush(stdin); rewind(stdin);setbuf(stdin, NULL);

C语言缓冲区之 gets(str);fflush(stdin); rewind(stdin);setbuf(stdin, NULL);

作者头像
瑞新
发布于 2020-07-07 06:46:08
发布于 2020-07-07 06:46:08
2.8K00
代码可运行
举报
运行总次数:0
代码可运行

清空键盘缓冲区很多种方法,如用fflush(stdin); rewind(stdin);setbuf(stdin, NULL);前两者仅对windows有用,最后一个则对Linux系统也适用。那么为什么需要清空键盘缓冲区呢? 以下几个实例:

Sample one

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
01	#include <stdio.h>
02	
03	int main(void)
04	{
05	char ch1;
06	char ch2;
07	
08	ch1 = getchar();
09	ch2 = getchar();
10	printf("%d %d", ch1, ch2);
11	return 0;
12	}

程序的本意很简单,就是从键盘读入两个字符,然后打印出这两个字符的ASCII码值。可是执行程序后会发现出了问题:当从键盘输入一个字符后,就打印出了结果,根本就没有输入第二个字符程序就结束了。例如用户输入字符’a’, 打印结果是97,10。这是为什么呢?

【分析】:

scanf()和getchar()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车(n)而结束的,这个n会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符n,这样第二次的读入函数直接从缓冲区中把n取走了,显然读取成功了,所以不会再从终端读取!其实这里的10恰好是回车符!这就是为什么这个程序只执行了一次输入操作就结束的原因!

【解决办法】:

清空缓冲区的残留数据。

使用 fflush(stdin); 或 rewind(stdin); 均可起到清空键盘缓冲区的作用,这两个函数均包含在stdio.h这个头文件中

修正后的写法: Sample two

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
01	 
05	
06	#include <stdio.h>
07	
08	int main()
09	{
10	char ch1;
11	char ch2;
12	
13	scanf("%c", &ch1);
14	printf("ch1 = %d", ch1);
15	
16	fflush(stdin);
17	
18	scanf("%c", &ch2);
19	printf("ch2 = %d", ch2);
20	return 0;
21	}

上面的实例只适用于Windows系统,在Linux环境下上面两种写法都是不起作用的,所以还要换个函数。

Sample three

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
01	 
07	
08	#include <stdio.h>
09	
10	int main()
11	{
12	char ch1;
13	char ch2;
14	
15	scanf("%c", &ch1);
16	printf("ch1 = %d", ch1);
17	
18	setbuf(stdin, NULL); 
19	
20	scanf("%c", &ch2);
21	printf("ch2 = %d", ch2);
22	return 0;
23	}

资料参考:http://www.ludou.org/c-clear-buffer-area.html

gets 在前面从键盘输入字符串是使用 scanf 和 %s。其实还有更简单的方法,即使用 gets() 函数。该函数的原型为:

include <stdio.h>

char *gets(char *str);

这个函数很简单,只有一个参数。参数类型为 char* 型,即 str 可以是一个字符指针变量名,也可以是一个字符数组名。

gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间。

下面将前面中使用 scanf 输入字符串的程序改一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# include <stdio.h>
int main(void)
{
    char str[20] = "\0";  //字符数组初始化\0
    printf("请输入字符串:");
    gets(str);
    printf("%s\n", str);
    return 0;
}

输出结果是: 请输入字符串:i love you i love you

可见,gets() 函数不仅比 scanf 简洁,而且,就算输入的字符串中有空格也可以直接输入,不用像 scanf 那样要定义多个字符数组。也就是说: gets(str); 完全可以取代: scanf("%s", string); 不仅代码更简洁,而且可以直接输入带空格的字符串。同样,前面章节中,对字符指针变量所指向的内存单元进行初始化也可以用 gets(),下面将那个程序也改一下,将 scanf 换成 gets():

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# include <stdio.h>
int main(void)
{
    char str[30];
    char *string = str;  //一定要先将指针变量初始化
    printf("请输入字符串:");
    gets(string);  //也可以写成gets(str);
    printf("%s\n", string);  //输出参数是已经定义好的“指针变量名”
    return 0;
}

输出结果是: 请输入字符串:Hi i…like you Hi i…like you

此外,关于使用 gets() 函数需要注意:使用 gets() 时,系统会将最后“敲”的换行符从缓冲区中取出来,然后丢弃,所以缓冲区中不会遗留换行符。这就意味着,如果前面使用过 gets(),而后面又要从键盘给字符变量赋值的话就不需要吸收回车清空缓冲区了,因为缓冲区的回车已经被 gets() 取出来扔掉了。下面写一个程序验证一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# include <stdio.h>
int main(void)
{
    char str[30];
    char ch;
    printf("请输入字符串:");
    gets(str);
    printf("%s\n", str);
    scanf("%c", &ch);
    printf("ch = %c\n", ch);
    return 0;
}

输出结果是: 请输入字符串:i love you i love you Y ch = Y

我们看到,没有清空缓冲区照样可以输入’Y’,因为 gets() 已经将缓冲区中的回车取出来丢掉了。如果前面使用的不是 gets() 而是 scanf,那么通过键盘给 ch 赋值前就必须先使用 getchar() 清空缓冲区。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/04/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
江哥带你玩转C语言 | 05-printf 和 scanf 函数
printf函数 printf函数称之为格式输出函数,方法名称的最后一个字母f表示format。其功能是按照用户指定的格式,把指定的数据输出到屏幕上 printf函数的调用格式为: printf("格式控制字符串",输出项列表 ); 例如:printf("a = %d, b = %d",a, b); 非格式字符串原样输出, 格式控制字符串会被输出项列表中的数据替换 注意: 格式控制字符串和输出项在数量和类型上***必须一一对应*** ---- 格式控制字符串 形式: %[标志][输出宽度][.精
极客江南
2021/07/11
1.3K0
c语言:C语言清空输入缓冲区在标准输入(stdin)情况下的使用
分析:并没有输入字符,直接就输出了“hello bit”,因为在点击回车(‘\n’)时,相当于输入了一个字符,那么我们需要进行清空缓冲区处理
用户7886150
2021/02/14
3.1K0
详解C/C++输入输出
C/C++输入输出很多,在不同的情况会用不同的输入输出,有的题目在输入时可能换一种输入输出就能不会TLE,有的输入可能要循环输入,但是可以换一种输入直接就能把所有数据输入进去。C/C++有哪些常用的输入输出,在什么时候用它们,这篇博客我会一一详解。
摆烂小白敲代码
2024/09/23
3060
详解C/C++输入输出
关于stdin流以及缓冲区浅谈
   突然觉得自己看了很多别人写的东西,学到很多,可惜以后每次都遇到问题忘了又得去网上一通乱找,还找不到自己当初看的写的较好一些东西资料,索性决定从现在起把自己每天获得的看到的一些东西和总结写到博客里面。
渴望飞翔的猪
2022/07/17
1.4K0
清除 C\u002FC++ 中的输入缓冲区
theme: channing-cyan highlight: a11y-dark
鲸落c
2022/11/14
9040
一文带你读懂C/C++语言输入输出流与缓存区
有没有发现,基本上所有的C语言入门书籍,或者是我们的教程里面,第一个C语言程序实体,都是“Hello Word!”;我不知道这是不是行业的“潜规则”,总之,它把无数的程序员带进了计算机的世界,步入了代码的大坑里,所以你好,世界!
李肖遥
2020/06/24
1.9K0
清除 C/C++ 中的输入缓冲区
什么是缓冲区? 临时存储区域称为缓冲区。所有标准输入和输出设备都包含一个输入和输出缓冲区。在标准 C/C++ 中,流被缓冲,例如在标准输入的情况下,当我们按下键盘上的键时,它不会发送到您的程序,而是由操作系统缓冲,直到时间分配给那个程序。
鲸落c
2023/05/23
1.1K0
一文带你读懂C/C++语言输入输出流与缓存区
有没有发现,基本上所有的C语言入门书籍,或者是我们的教程里面,第一个C语言程序实体,都是“Hello Word!”;我不知道这是不是行业的“潜规则”,总之,它把无数的程序员带进了计算机的世界,步入了代码的大坑里,所以你好,世界!
李肖遥
2020/06/23
1.2K0
day30-标准IO(2022.3.1)
——》标准IO,其本质就是调用了系统IO函数,另外定义了缓冲区和添加了一下处理步骤。
天天Lotay
2022/12/02
4350
day30-标准IO(2022.3.1)
C语言 getchar()原理及易错点解析
这个问题转载自n_s_X14,但是作者在文章最后留了一个问题,现在在这里给大家解释一下原因。
全栈程序员站长
2022/11/02
1.4K0
C语言 getchar()原理及易错点解析
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
<font color="blue">考点1:"普通/占位符",输入时普通字符必须原样输入</font>
小徐在进步
2024/09/30
3050
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
C语言入门系列之11.文件和文件操作
文件是指一组相关数据的有序集合,这个数据集有一个名称,叫做文件名。 我们在前面的已经使用到了很多文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。
cutercorley
2020/07/23
1.5K0
C语言入门系列之11.文件和文件操作
C语言的文件操作_C语言调用文件
C文件操作用库函数实现,包含在stdio.h中。 文件使用方式: 打开文件→文件读/写→关闭文件
全栈程序员站长
2022/09/23
9.4K0
C语言的文件操作_C语言调用文件
【期末复习】考试月来临!☀️C语言复习,这一篇带你逃离挂科区!(上)⭐️
注意:变量必须先定义后使用,在变量取值时,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据
小丞同学
2021/08/16
8680
c语言getchar()的用法_c=getchar()
该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读取错误,则返回 EOF(-1)。所以 getchar() 函数返回值要用 int 整型变量来存储
全栈程序员站长
2022/11/02
7.8K0
c语言getchar()的用法_c=getchar()
[c语言日寄]数据输入
在C语言的世界里,数据输入是程序与用户交互的重要环节。无论是简单的计算器程序,还是复杂的系统软件,都需要从用户那里获取数据,然后进行处理和输出。今天,我们就通过一个简单的程序来深入探讨数据输入的实现方法、相关知识点以及一些拓展应用。
siy2333
2025/03/24
860
开讲啦:Chap 10 对文件的输入输出
表示file1.dat文件存放在D盘中的CC目录下的temp子目录下面,文件标识常被称为文件名,文件名主干的命名规则遵循标识符的命名规则,后缀用来表示文件的性质,如:
石璞东
2021/10/25
6850
C语言中从键盘输入字符串时的一些问题[通俗易懂]
scanf()在输入字符串时有很大的弊端, 例如: 1). scanf()在从键盘读入字符时并不会根据所定义的字符数组的大小来控制读入多少个 , 而是从scanf( ) 中传入的地址开始一直访问下一个元素的内存 , 碰见空格符或者回车符时才停止读入并存入结束符’\0’ , 这就有可能造成了一个在C中非常严重的问题 , 访问非法内存 . 如果所输字符数量大于字符数组的长度 , 当scanf()将把字符存入字符数组的最后一个元素后 , scanf()还会继续往后访问内存 , 将接收的字符继续存入 , 但之后的内存是我们未申请的非法内存 , 会发生未知错误 , 例如以下代码: 2). 第二点也就是第一点中的遇到空格符停止读入并存入结束符’\0’, 也就是说scanf()存不了空格符
全栈程序员站长
2022/11/16
1.8K0
C语言中从键盘输入字符串时的一些问题[通俗易懂]
【C语言】getchar 函数的正确使用
也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
全栈程序员站长
2022/11/02
1.7K0
【C语言】getchar 函数的正确使用
C语言进阶-文件操作超详解
scanf/printf、fscanf/fprintf、sscanf/sprintf函数对比
用户9645905
2022/11/30
1K0
C语言进阶-文件操作超详解
相关推荐
江哥带你玩转C语言 | 05-printf 和 scanf 函数
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验