针对scanf()的缓冲区
针对scanf()的缓冲区
操作方法
- 01
针对scanf()的缓冲区#include <stdio.h> main(){ char a, b,c; scanf("%c",&a); scanf("%c",&b); scanf("%c",&c); printf("%c,%c,%c",a,b,c);} %c是能接收空格和回车(既是确定又是字符)的当输入x 回车 两个同时被释放,被变量a,b分别获取输入y 回车 y被释放,回车准备释放状态,y被c获取和getchar()缓冲区原理一样把scanf()怎么去掉回车?前面很早就说过了,在%前面加个空格#include <stdio.h>main(){ char a, b,c; scanf("%c",&a); scanf(" %c",&b); scanf(" %c",&c); printf("%c,%c,%c",a,b,c);} 上面输入x 回车 两个同时被释放 x被a获取 回车到了第2个scanf的那个空格里输入y 回车 y被b获取 回车到了第3个scanf那个空格里输入z 回车 z被c获取 回车则是准备释放状态中因为scanf()是格式输入函数,还记得我说过scanf("\n%c",&a),前面那个\n你可以忽略吧scanf(" %c",&a)有scanf("%c ",&a)有什么不同空格在前你可以忽略空格直接打x, 也可以按空格 x或者回车 x 你一开始打空格或回车就在那个空格里了,不会再跑进缓冲区,你直接忽略那个空格打x,x进入缓冲区被释放的时候会直接进到%c里,无视前面的空格空格在后,它就不再无视了,你输入x 回车 两个同时释放 x进了%c 回车到了那个空格 此时缓冲区是空的,等待着你的输入,直到你输入一个值,回车之后,才算结束,似乎缓冲器总是要至少留一个准备释放状态的值,它才可以结束输入其实空格在后也可以实现,像这样#include <stdio.h>main(){ char a,b,c; scanf("%c ",&a); scanf("%c ",&b); scanf("%c",&c); printf("%c,%c,%c",a,b,c);} 以上输入x-回车-y-回车-z-回车和输入xyz-回车结果一样的下面再来个缓冲区问题,看程序#include <stdio.h>main(){ char a[20], b[20],c[20]; scanf("%s",a); scanf("%s",b); scanf("%s",c); printf("%s,%s,%s",a,b,c);} 输入abc 回车 def 回车 ghi 回车结果是abc,def,ghi在scanf()%s格式中,scanf会按照%s的格式对缓冲区按字节顺序扫描,当扫描到回车或空格时,结束扫描,然后在扫描到的数据(不含回车空格)发送数组a里,此时,缓冲区为空,继续等待输入,输入def 同样是除去回车 发送到数组b里缓冲区为空,继续等待输入,输入ghi 回车 ghi发送到数组c里 但最后一个回车留到缓冲区作为准备释放状态,输入结束无论你在开始输入前打多少空格或回车,都不会留到缓冲区,直到你开始输入数据后,回车或空格,sacnf()%s格式会认为输入结束,且不让回车和空格进缓冲区,但是最后输入完成的那个回车会留到缓冲区等待释放(因为后面没%s了),输入结束scanf("%c%c%c",a,b,c);这个缓冲原理应该理解了吧输入x 回车 两个同时释放 到了 ab里输入y 回车 同时释放 y到了 c里 回车为准备释放状态如果输入xyz 回车 都释放出来 xyz依次被abc获取 回车为准备释放状态scanf()%d格式同样也有缓冲原理,但是对回车空格免疫,道理很简单,数字格式拒绝字符格式二、针对gets()的缓冲问题看程序#include <stdio.h>main(){ char a[20],b[20]; printf("请输入第一组字符串:\n"); scanf("%s",a); puts("请输入第二组字符串"); gets(b); printf("%s,%s",a,b); } 这个程序不是我们想要的结果我们输入hello 回车 此时hello和回车同时从缓冲区里被释放,hello被数组a获取,回车为准备释放状态,等回车到了gets()那里,由于gets()碰到回车会认为输入结束,所以还没等你输入,gets()就已完成输入,则数组b为空,程序结束gets()的缓冲原理,假设gets(b),当我们输入hello 此时hello在缓冲区,再输入回车,gets()遇到回车会认为输入结束,但它不会让回车进入缓冲区,回车没进入缓冲区,也就谈不上释放,也就不会在进入以后的scanf()或者getchar(),这里的回车只有确定功能没有字符功能,当打完回车 hello会被释放,被b获取,如果包含空格,也会连同空格,存到数组b里(空格占一个字符),此时的缓冲区完全是空,没有准备释放的值,不会继续等待你的输入(gets是这样),除非下面程序还要输入。gets()取值是字符串(字符串也可以是一个字符),所以gets(b),而非b=gets()所以程序这样就可以#include <stdio.h>main(){ char a[20],b[20]; puts("请输入第一组字符串"); gets(a); printf("请输入第二组字符串:\n"); scanf("%s",b); printf("%s,%s",a,b); } 三、两者比较scanf("%s",a);,gets(a)遇到回车和空格scanf("%s",a);以遇到空格为输入结束的标志(前提是缓冲区有值),值还在缓冲区等回车来确定释放,但%s格式不会让回车和空格进入缓冲区,也不会让空格和回车存入%s格式的a里scanf("%s",a);遇到回车结束和释放同时进行,回车不进入缓冲区gets(a),以遇到回车为结束的标志,不管缓冲区有没有值,遇到回车马上结束,回车不进入缓冲区gets(a);遇到空格等于遇到字符,没特殊含义scanf("%c",&a);,a=getchar()遇到回车和空格scanf("%c",&a);,遇到空格会直接被a获取,然后进入缓冲区等待回车,回车也进入缓冲区和缓冲区的值一起释放scanf("%c",&a);,遇到回车也会直接被a获取,且同时和回车一起从缓冲区释放a=getchar()原理和scanf("%c",&a);,一样 因为scanf("%c",&a)等于a=getchar()还有这种#include <stdio.h>main(){ char a; int b; scanf("%c",&a); scanf("%d",&b); printf("%c,%d",a,b); } 输入a1b4,在缓冲区是怎样的,首先a1b4先进入缓冲区,再按回车 a1b4和回车一起释放,scanf()函数本质上是一种"模式匹配"函数,首先第一个 scanf()读取缓冲区里的数据 %c格式只能保存一个字符,所以a被第一个scanf()拿走了,1b4继续留在缓冲区,接着第2个scanf()读取,%d格式获取1成功,但获取到b时,由于格式不匹配,放弃b ,由于%d已经获取了一个数字,所以4也放弃了, b4和回车就继续留到缓冲区里准备释放中