学习笔记:scanf的缓冲区机制(超详解)以及getchar的吸收用法和注意事项

温馨提示:本文正文阅读时间大约为3分钟,主要说明scanf的缓冲区机制以及getchar的吸收用法和注意事项。本人现电子信息工程大一,写该笔记纯粹为了记录思考过程和易错点,方便以后查阅。其中的定义是个人的说法,仅便于更好的理解。如果表达有误欢迎指正,同时也感谢指正!

一、先说结论:

1、getchar()的吸收用法:

(1)在哪用:scanf后和gets之前,防止留在缓冲区的空白字符(回车)被gets读入

(2)用几次:取决于最后一次使用的scanf的有效空白字符

对于实际问题:还是在每一个scanf后都都加一个getchar为好,以防忘记释放缓冲区。

2、scanf("%x",&xxx)输入的用法:

对于scanf("%s",str);因为%s会跳过空白字符,从第一个非空白字符开始一直读到第一个空白字符为止(空白字符一般指空格(0x20),回车(0x0D)、换行(0x0A),制表符(0x09)、垂直制表符(0x0B)和换页(0x0C)。即scanf是在有效输入后再遇到回车,空格就结束,但并不会自动将回车、空格从缓冲区中释放,剩余的字符将会留在输入缓冲区中等待下一次读取。

解释:1scanf不会读入空白字符,故不会吸收回车等空白字符。这些空白字符只有部分会留在缓冲区(接下来讲解为什么是部分)

(2)从第一个非空白字符开始一直读到第一个空白字符:就是先打一堆空格、回车都不会作为输入,直到遇到非空白字符才输入,再次遇到空白字符就作为结束标志。

二、疑惑的点:为什么上一次输入后的scanf的回车不会直接作为下一次scanf的结束标志?

三、定义:先定义一个概念,在有效输入(对于%d:输入整型,对于%s:输入字符串(不包含空白字符))前的空白字符叫无效空白字符,而有效输入后的空白字符叫有效空白字符

之所以区分有效和无效:

  1. 是因为前面输入的在缓冲区中会被自动释放,故后文都解释为不会输入到缓冲区中,而有效输入和有效空白字符才都会输入到缓冲区中
  2. 无效空白字符不会作为结束输入的标志,而有效空白字符才会作为结束输入的标志

这里要注意的是,在有效空白字符的组成:若干个空格,且仅有一个回车(这个回车在最后作为输入到缓冲区结束的标志)

例1:scanf读取整型变量

	int a=2;
	scanf("%d",&a);
	printf("a=%d",a);

输入:[空格] 1[空格] [回车]

输出:a=1

分析:无效空白字符([空格])不会作为结束输入的标志,有效输入1以及后面的有效空白字符([空格] [回车])会传入到缓冲区,其中1赋给a,同时从缓冲区释放,而有效空白字符则会留在缓冲区中。

例2:scanf读取字符串

void main() {
	FILE *in, *out;
	char ch,infile[10],outfile[10],str[30];
	printf("Please enter the infile name:\n");
	scanf("%s",infile);
	
	printf("Please enter the outfile name:\n");
	scanf("%s",outfile);
	getchar();
	
	if((in = fopen(infile,"w"))== NULL) {
		printf("Cannot open infile.\n");
		exit(0);
	}
	gets(str);
	fprintf(in,"%s",str);
	fprintf(stdout,"%s",str);	
	fclose(in);
}

输入:a1.txt[回车]b1.txt[回车]

现象:到最后缓冲区中只有b1.txt后面的[回车],所以用一个getchar()来吸收[回车],以保证后续可以正常输入str(避免被后续的gets(str);作为结束的标志)

getchar();
getchar();

如果改为两个getchar(),那么输入:a1.txt[回车]b1.txt[空格][回车]

其b1.txt后只能跟一个空格和一个回车(根据无效空白字符的定义)

//正常来说有效空白字符就一个回车吧……对于正常人来说,谁在知道了scanf读不了空格的前提下还在回车前输入空格啊喂,所以用一次getchar()就行,在gets()前。

例2程序的具体分析:

两个scanf连续输入,第一次输入的a1.txt时,其前面的无效空白字符不会输入到缓冲区中,而只有有效输入和其后面的有效空白字符才都会输入到缓冲区中。

到了下一次的输入时,之前的有效空白字符会作为a2.txt有效输入前的无效空白字符故并不会影响第二次的输入(这也是我一开始疑惑的点,为什么第一次输入后的scanf的回车不会直接作为下一次scanf的结束标志)。

关键点来了:上一次输入时的有效空白字符变成了无效空白字符,即被释放,此时缓冲区中只剩下第二次有效输入后的有效空白字符。

所以对于连续的scanf而言,只需在最后一个scanf后释放,即一个scanf跟一个getchar();并不需要每个scanf后都加getchar()

   	printf("Please enter the infile name:\n" );
	scanf("%s",infile);
	getchar();//没必要 
	
	printf("Please enter the outfile name:\n" );
	scanf("%s",outfile);
	getchar();

总结:

1、getchar()的吸收用法:

在哪用:scanf后和gets之前,防止留在缓冲区的空白字符(回车)被gets读入

用几次:取决于最后一次使用的scanf的有效空白字符

对于实际问题:还是在每一个scanf后都都加一个getchar为好,以防忘记释放缓冲区。

2、scanf("%s",str)的输入注意事项:

上一次的scanf的有效空白字符会留在缓冲区里,新的scanf输入会覆盖缓冲区,其新的有效输入后的有效空白字符会留在缓冲区里,故连续使用scanf时,只需在最后一个scanf后吸收即可。

感谢观看~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值