scanf的缓冲区问题

在写图书馆管理系统的时候,利用scanf输入函数时,莫名其妙把自己用死了。
这里用简单的代码来描述我遇到的问题

#include<stdio.h>
int main(){ 
	int a, b;
	char c;
	printf("输入两个整数"); 
	scanf("%d %d", &a, &b);
	printf("输入一个字符"); 
 	scanf("%c", &c);
 	printf("%d %d %c\n", a, b, c);
}

输入的格式为: 1 2 c
输出为:在这里插入图片描述
当我输入完 1 2后,本应该在输入字符a可结果就显示成这样。
这就是典型的scanf缓冲区问题

当我们输入完 1 2后按下回车键,输入缓冲区里存放着1 2 \n,第一次scanf读走1给a,2给b,中间的空格丢弃,此时第一句scanf已经读完。但是缓冲区里还留着一个\n,当第二scanf读入时,首先检查缓冲区,发现缓冲区里还有\n,而且正好匹配%c,于是直接读走\n给c。
关于缓冲区(我遇到的这个问题显然时行缓冲区)
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内冲空间预留了一定的储存空间,这些储存空间用来缓冲输入或者输出的数据,这部分预留的空间就叫做缓冲区。
缓冲区根据其对应的时输入还是输出,分为输入缓冲区和输出缓冲区。
缓冲区时一块内存区,它在输入输出设备和cpu之间,用来缓存数据。他是低速的输入输出设备和高速的cpu能够协调共工作,避免低速的输入和输出设备占用cpu。
缓冲区分为三种类型:全缓冲,行缓冲和不带缓冲

  1. 全缓冲:当填满标准I/O缓存后才进行实际的I/0操作。其经典代表就是对磁盘文件的读写。

  2. 行缓冲:当输入和输出中遇到换行符,执行真正的I/O操作。这时,我们输入的字符优先存放在缓冲区,当按下回车键换行时,才进行实际的I/O操作。其经典的标准输入(stdin)和标准输出(stdout)

  3. 不带缓冲也就是不进行缓冲,标准出错情况stderr时其典型代表,这使得出错信息可以直接尽快显示出来。
    C对stdin、stdout和stderr的缓存特征没有强行的规定,以至于不同的系统可能有不同的stdin、stdout和stderr的缓存特征。目前主要的缓存特征是:stdin和stdout是行缓存;而stderr是无缓存的。
    缓冲区的大小
    如果我们没有自己设置缓冲区的话,系统就会默认为标准输入输出设置一个缓冲区,这个缓冲区的大小通常时512个字节的大小。
    缓冲区大小由stdio.h头文件中宏BUFSIZ定义
    缓存区的刷新
    下列情况会发生缓冲区的刷新:

  4. 缓冲区满

  5. 缓冲区遇到\n的时候

  6. 程序结束

  7. 使用特定函数刷新缓存区
    c语言中在读取键盘数据时,一般时带缓存的数据输入,需要回去键才能完成该行数据的输入确认
    而scanf()函数对这个回车确认符并不进行处理,回车符会留在输入缓冲区中,因此,在下一个读‘字符’操作函数(getchar(),scanf(“%c”),gets())运行时,会读到这个字符,而在读取值型数据或者字符串时,scanf()会从第一个非空白字符(空白字符指:回车,空格,TAB键)开始读取,自动忽略前面的空白字符,而遇到空白字符结束该类型数据的输入。
    解决方法

  8. 用fflush(stdin)命令强行刷新输入缓存,丢弃输入缓存中的数据

#include<stdio.h>
int main(){ 
	int a, b;
	char c;
	printf("输入两个整数"); 
	scanf("%d %d", &a, &b);
	printf("输入一个字符");
	fflush(stdin);  //不管缓存中有没有数据,强行清除
 	scanf("%c", &c);// //这里用户输入一个字符
 	printf("%d %d %c\n", a, b, c);//结果没有问题 
}
  1. 前面有读数据操作,现在要执行读字符操作,则可用getchar()来吃掉前面的回车确认
#include<stdio.h>
int main(){ 
	int a, b;
	char c;
	printf("输入两个整数"); 
	scanf("%d %d", &a, &b);
	printf("输入一个字符");
	getchar(); //吃掉回车确认符
 	scanf("%c", &c);// //这里用户输入一个字符
 	printf("%d %d %c\n", a, b, c);//结果没有问题 
}
  1. rewind(stdin)清除标准输入的按键缓冲区。rewind函数是把指定流的读写指针重新指向开头
#include<stdio.h>
int main(){ 
	int a, b;
	char c;
	printf("输入两个整数"); 
	scanf("%d %d", &a, &b);
	printf("输入一个字符");
	rewind(stdin) ;//是把文件指针回绕到文件起始处。
 	scanf("%c", &c);// //这里用户输入一个字符
 	printf("%d %d %c\n", a, b, c);//结果没有问题 
}

总结:
在网上看了很多关于scanf缓冲区的问题所总结出来的,scanf还有很多其他用法。

scanf输入缓冲区问题是指在使用scanf函数进行输入时,输入缓冲区中可能会残留上一次输入的换行符\n,导致下一次输入不符合预期。例如,当我们输入完1 2后按下回车键,输入缓冲区里存放着1 2 \n。第一次scanf读走1给a,2给b,中间的空格丢弃,此时第一句scanf已经读完。但是缓冲区里还留着一个\n,当第二次scanf读入时,首先检查缓冲区,发现缓冲区里还有\n,而且正好匹配%c,于是直接读走\n给c。这就是典型的scanf缓冲区问题。 为了解决scanf输入缓冲区问题,可以使用以下方法: 1. 使用fflush(stdin)命令强行刷新输入缓冲,丢弃输入缓冲中的数据。这个方法可以清除缓冲区中的换行符等残留数据,确保输入的正确性。 2. 使用getchar()函数吃掉前面的回车确认符。在执行读取字符操作之前,使用getchar()读取并丢弃缓冲区中的回车符,确保下一次输入的正确性。 3. 使用rewind(stdin)清除标准输入的按键缓冲区。rewind函数是把指定流的读写指针重新指向开头,可以清除输入缓冲区中的残留数据。 通过使用上述方法,可以有效地解决scanf输入缓冲区问题,确保输入的准确性和一致性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [scanf缓冲区问题](https://blog.csdn.net/qq_45908718/article/details/117394732)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望北i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值