黑基网 首页 公开课 编程课程 查看内容

针对scanf()和gets()的缓冲问题

2016-4-8 15:58| 投稿: | 查看: 2355| 评论: 0

摘要: 一、针对scanf()的缓冲区#include stdio.hmain(){ char a, b,c; scanf("%c",a); scanf("%c",b); scanf("%c",c); printf("%c,%c,%c",a,b,c);}%c是能接收空格和回车(既是确定又是字符)的当输入x 回 ...

     友情提醒:公开课需要专用客户端播放,否则只能播放10多秒!点击下载    

一、针对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和回车就继续留到缓冲区里准备释放中

鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

返回顶部