`
猫太的鱼
  • 浏览: 239264 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

getchar、scanf以及缓冲区的概念

阅读更多
     1、getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了。

      getch()和getche()是conio.h中的库函数,它的作用是从键盘接收字符,getchar带有回显。
      与前面两个函数的区别在于: getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。
    #include "stdio.h"  
    #include "stdlib.h"  
    int main(void)  
    {  
        char c;  
        while((c=getchar())!='\n')     //每个getchar()依次读入一个字符  
            printf("%c",c);            //按照原样输出  
        printf("\n");  
        system("pause");  
        return 0;  
    }  

       程序运行时,首先停下来,等你输入一串字符串,输入完毕后,它把你输入的整个字符串都输出来了,咦,你不是说getchar()只返回第一个字符么,这里怎么?

      因为我们输入的字符串并不是取了第一个字符就把剩下的字符串丢掉了,它还在我们的内存中,好比,开闸放水,我们把水放到闸里去以后,开一次闸就放掉一点,开一次就放掉一点,直到放光了为止,这里开闸动作就相当于调用一次getchar()。我们输入的字符串也是这么一回事,首先我们输入的字符串是放在内存的缓冲区中的,我们调用一次getchar()就把缓冲区中里出口最近的一个字符输出,也就是最前面的一个字符输出,输出后,就把它释放掉了,但后面还有字符串,所以我们就用循环把最前面的一个字符一个个的在内存中释放掉,直到满足循环条件退出为止。

     例子中循环条件里的'\n '实际上就是你输入字符串后的回车符,所以意思就是说,直到遇到回车符才结束循环,而getchar()函数就是等待输入(或缓冲区中的数据)直到按回车才结束,所以实现了整个字符串的输出。当然,我们也可以把循环条件改一下,比如while ((c=getchar())!='a'),什么意思呢,意思就是遇到字符'a'就停止循环,当然意思是如果你输入“12345a213123 ”那么只会输出到a前面的那个字符,结果是12345。

     再次注意:用getchar()它是从“流”中间去读取,所以第一个getchar()接受的是刚刚中断的流队列中即将出列的第一个字符(不限于回车符,上面举过例子了),如果流队列不为空,执行getchar()就继续放水,直到把回车符也放空为止,空了之后再在执行getchar()就停下等待你的输入了;我们用getch()为什么每次都是等待用户的输入呢?因为getch()是从键盘接收,即时的接收,并不是从stdin流中去读取数据。

     下面是我的讨论:

     先来一段code:
    #include "stdio.h"  
    #include "stdlib.h"  
    int main(void)  
    {  
        char c;  
        for(;(c=getchar())!='a';)  
            printf("%c",c);  
        getchar();  
        c=getchar();  
        printf("%c",c);  
        system("pause");  
        return 0;  
    }  

输入:  ssss回车

得到:   ssss

           光标处(等待输入)


说明:由于一直没有输入字符a,所以此时程序没有结束,进入到for循环后一直没有退出。键入回车后,运行c=getchar(),依次从缓冲区内取出(for循环):'s''s''s''s'' ' 包括回车的换行符,并将其全部打印了出来。。

如果我们输入:ssssa回车

得到:ssss光标处(等待输入)


说明:程序读入到字符a的时候跳出了for循环,但是由于我们用getchar();清除了换行符'\n ',后面第7句c=getchar();需要你输入一个字符(因为ssssa后面并没有新的字符),所以程序仍然没有结束。如果我们注释掉getchar();这一句,那么c=getchar();这行代码就可以读取ssssa后面的回车符号了,就可以得到这样的输出: 

       ssss

       光标处(程序结束)


这个输入ssssa中的回车中的换行符'\n '就被c=getchar();这一句读取并输出了。

       总结:

       键盘输入的字符都存到缓冲区内,一旦键入回车,getchar就进入缓冲区读取字符,一次只返回第一个字符作为getchar函数的值,如果有循环或足够多的getchar语句,就会依次读出缓冲区内的所有字符直到'\n '。要理解这一点,之所以你输入的一系列字符被依次读出来,是因为循环的作用使得反复利用getchar在缓冲区里读取字符,而不是getchar可以读取多个字符,事实上getchar每次只能读取一个字符。如果需要取消' \n'的影响,可以用getchar();来清除,这里getchar();只是取得了'\n '但是并没有赋给任何字符变量,所以不会有影响,相当于清除了这个字符,还要注意的是这里你在键盘上输入ssss看到的回显正是来自于getchar的作用,如果用getch就看不到你输入了什么。
          2、scanf

      scanf这个库函数比较奇怪,而且存在一定的缺陷,所以很多人都不用了,这里还是要简单介绍一下。

      scanf输入字符串、整型、实型等数据判断的方式都一样,回车、空格、tab键都认为是一个数据的结束,当然字符的话,一个字符就是结束了。回车、空格等都有对应的ASCII码,所以用scanf输入字符时要小心这些东西被当成字符输进去,而输入字符串和整型、实型等数据时这些都被当成分隔符而不会被输入到字符数组或变量里。当然如果输入格式不是"%s%s"而是"%s,%s"分隔符就是逗号了。

     说了这么多举几个例子:
    #include "stdio.h"  
    int main(void)  
    {  
        char n1[10];  
        char n2[10];  
        scanf("%s",n1);  
        scanf("%s",n2);  
        printf("n1=%s,n2=%s",n1,n2);  
        return 0;  
    }  

输入:

hello回车

world回车


得到如下的输出:

n1=hello,n2=wolrd光标处(程序结束)

       这里hello后面就是输入再多个回车、空格也不会被赋值到n2中的,因为使用scanf函数输入字符串的时候他们只是被当做分隔符。另外就是输入n2的时候,n2后面的那个回车也被当做了分隔符,所以输出的时候,只是简单的输出了n1和n2的内容,而没有输出回车换行符。


如果输入:

hello回车

光标处(等待输入)


说明回车被认成分隔符,所以程序还要你输入一个字符串来赋给n2。

其实这时缓冲区里是有一个'\n '被留下来的,程序改成这样:
    #include "stdio.h"  
    int main(void)   
    {  
        char n1[10];   
        char n2[10];  
        char n3,n4;   
        scanf("%s",n1);   
        scanf("%s",n2);   
        printf("n1=%s,n2=%s",n1,n2);  
        n3=getchar();      //n3读取了n2后面的那个回车字符并输出  
        printf("%c",n3);  
        //n4=getchar();  
        //printf("%c",n4);   
        return 0;  
    }   

输入:

hello回车

world回车


得到: 

n1=hello,n2=wolrd

光标处(程序结束)


如果取消最后两行的注释,同样的输入得到:

n1=hello,n2=wolrd

光标处(等待输入)

说明此时缓冲区内只有一个'\n ',第二个getchar就需要你再输入一个字符了,缓冲区内已经没有字符了。

   scanf不会把回车、空格赋给字符串但是会赋给字符,就如同getchar一样,这时就要考虑'\n '的存在了。

比如:
    #include "stdio.h"  
    int main(void)   
    {  
        char n1[10];  
        char n2;  
        scanf("%s",n1);  
        scanf("%c",&n2);  
        printf("n1=%s,n2=%d",n1,n2);  
        return 0;  
    }  

输入:

hello回车

得到:

n1=hello,n2=10光标处(程序结束)    //10是'\n '的ASCII码.

如果输入:

hello 空格回车(一定要有回车,因为scanf也是要等回车,准确说是' \n'才会去读缓冲区的。)

得到:

n1=hello,n2=32光标处(程序结束)    //32是空格的ASCII码。

再罗嗦一下,如果最后一句输出n2=%d改成n2=%c,则输入:

hello回车

得到:

n1=hello,n2=

光标处(程序结束)


是不是和getchar一样可以把'\n '读出来呢,呵呵。

总结一下就是:

如果scanf输入的不是字符,那么分隔符为回车,空格、tab键时,两个数据之间的分隔符只是起区别两个数据的作用,把分隔好的两个数据分别赋值到各自定义好的变量或数组中去,两个数据之间的分隔符被从缓冲区读出但是不起任何作用,当然最后一个'\n '会被留在缓冲区内,除非用getchar();或scanf("%c",&c);把它读出来。

回车是一定要有的,不管getchar还是scanf只要是通过缓冲区输入数据的函数都是等待回车键'\n '出现才进入缓冲区的。再来个整型数据、字符串、字符的混合例子:
    #include "stdio.h"  
    int main(void)   
    {  
        int a,b,c;  
        char n1[10];  
        char n2,n3;  
        scanf("%d%d",&a,&b);  
        scanf("%c",&n2);  
        scanf("%d",&c);  
        scanf("%s",n1);  
        scanf("%c",&n3);  
        printf("a=%d,b=%d,n2=%c,c=%d,n1=%s,n3=%c",a,b,n2,c,n1,n3);  
        return 0;  
    }  

输入:

12(若干空格或回车都不影响结果,这里用了回车)

34(这里还要求输入,因为scanf只得到了一个整型数据,而缓冲区内没有整型数据了。要有回车或空格表示这个数据结束了,留下来的空格或回车被下个%c接受,这里用了回车,可以试一下空格)

45 jfdkjfa(回车)


得到:

a=12,b=34,n2=

,c=45,n1=jfdkjfa,n3=

光标处(程序结束)


       这里说明一下过程:在前两个整型数据输入时,两个数据之间无论是回车还是若干空格都被scanf当做分隔符,好了,scanf读到分隔符(回车或空格)时,把第一个整型数据送到变量a中,缓冲区中留下分隔符和下面的整型数据,这时scanf再读当然先读分隔符,但是要求输入的还是整型数据(%d),所以分隔符被忽略,如果这时要求输入字符%c(不是字符串%s),那么分隔符将以一个字节的形式送到字符变量里,就如同这里的n2。同理可以知道c和n1的保存过程,最后的n3正是接收了输入时的最后一个回车。

好了如果看到这里你都理解了那么看最后一个例子:
    #include "stdio.h"  
    int main(void)  
    {  
        int a;  
        char ch;  
        scanf("%d",&a);  
        ch=getchar();  
        printf("%d,%c",a,ch);  
        return 0;  
    }  

输入:

95回车

得到:

95,

光标处(程序结束)


很明显这是由于分隔符(回车)被getchar读取并输出了,如果加入一句:getchar();
    #include "stdio.h"  
    int main(void)  
    {  
        int a;  
        char ch;  
        scanf("%d",&a);  
        getchar();  
        ch=getchar();  
        printf("%d,%c",a,ch);  
        return 0;  
    }  

输入:

95回车

c回车


得到:

95,c光标处(程序结束)
分享到:
评论

相关推荐

    SCANF和GETCHAR的区别,GETCHAR的妙用

    如果后续没有对应的getchar(),换行符将留在缓冲区中等待下一次读取。 在编程实践中,需要特别注意scanf和getchar的区别和使用时机。当需要按格式读取不同类型的数据时,应优先考虑使用scanf,同时注意输入格式符...

    scanf(), getchar(), 以及gets()函数注意点

    究其原因,是因为scanf()函数和getchar()函数都是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。读取时遇到回车符(\n)而结束的,这个\n 会一起读入输入流缓冲区的,所以第一次接受输入时取走...

    C++深入了解scanf()getchar()和gets()等函数

    在程序执行过程中,如果缓冲区中存在残留数据,scanf()、getchar()和gets()函数可能会直接从缓冲区中读取这些数据,而不是从键盘中读取新的数据。这可能会导致程序的执行结果与预期不同。 总结 在使用scanf()、...

    C语言清空输入缓冲区在标准输入(stdin)情况下的使用

    C语言清空输入缓冲区在标准输入(stdin)情况下的...本文主要介绍了C语言清空输入缓冲区在标准输入(stdin)情况下的使用,包括多种清空缓冲区的方法,以及每种方法的优缺点,最终推荐使用getchar函数来清空缓冲区。

    C语言输入缓冲区完全攻略!

    - 使用`fflush(stdin)`或`getchar()`等方法可以清除输入缓冲区中的内容,确保后续的`scanf`操作不受影响。 综上所述,理解C语言中输入缓冲区的工作机制及其与`scanf`函数交互的方式对于编写高效且可靠的程序至关...

    C语言中getchar, gets, 和 scanf 三种不同函数的区别

    然而,由于`gets()`在C11标准中被弃用,因为其存在严重的安全问题——没有对输入字符串的长度进行检查,可能导致缓冲区溢出。这使得`gets()`非常不推荐使用。为了安全地读取字符串,应该使用`fgets()`替代。例如,`...

    STM32实现printf和scanf源代码,保证能运行

    4. **接收缓冲区管理**: 需要维护一个接收缓冲区,用于暂存从UART接收到的字符,直到遇到换行符或其他分隔符。 5. **解析输入**: 根据输入格式字符串,解析接收到的字符,执行相应的操作。 压缩包中的"Ex001-串口...

    c语言输入的各种注意问题

    "C语言输入函数的注意问题" 在C语言中,输入函数是非常重要的概念,它们是从标准输入流...getchar函数是C语言中非常重要的输入函数,它们有其特点和用法,需要注意缓冲区的存在和清空问题,以及回车符和换行符的区别。

    C语言 中scanf详解.pdf

    但当输入不匹配或遇到非法数据时,可能会导致键盘缓冲区中存在未处理的输入,这需要开发者特别留意。 `scanf`处理字符串时,一个Enter键会被解析为两个字符:回车(ASCII码10)和换行(ASCII码13)。`getchar()`...

    C语言中输入输出流与缓冲区的深入讲解

    当调用输入函数scanf()时,输入函数会将我们输入的数字输入到输入缓冲区, 而当我们的输入缓冲区有内容时,再次输入将不会被执行, 而是直接跳过执行,将输入缓冲区的内容赋给变量; 1、为什么要引入缓冲区 例如,我们...

    C语言清除scanf()缓存的案例讲解

    通过本文的讲解,我们可以了解到scanf()函数读取输入缓冲区的内容带来的问题,以及如何使用flush函数和getchar函数清除输入缓冲区的内容。通过清除输入缓冲区的内容,可以避免scanf()函数读取缓存带来的问题,提高...

    程序设计-用scanf函数实现数据的输入.pptx

    4. **清除输入缓冲区**:在某些情况下,可能需要清除输入缓冲区中的剩余字符,这可以使用`getchar()`或`fflush(stdin)`来实现,但`fflush(stdin)`的行为在标准C中是未定义的,应谨慎使用。 理解并熟练运用`scanf`...

    关于fflush关于fflush关于fflush关于fflush

    因为缓冲区中有数据,所以 scanf 函数不会等待用户输入,而是直接从缓冲区中读取数据。 有人可能会说:“那么,在 scanf 函数后面加上 fflush(stdin) 不就行了?”然而,这是错误的!C 和 C++ 的标准中从来没有定义...

    第3章 键盘输入与屏幕输出-5用%c格式符输入数据时存在的问题1

    在修正后的程序中,`getchar()`函数被用来读取并丢弃缓冲区中的回车符,确保`%c`格式符能够正确读取用户期望的字符'a'。 以下是针对`%c`格式符输入数据问题的一些解决方案: 1. 使用`getchar()`:在读取`%c`之前...

    清空缓存区1

    本文将深入探讨C语言中的缓存区概念以及清空缓存区的必要性,并提供两种实用的清空方法。 【标签】:C语言 【正文】: 在C语言中,缓存区是内存中的一块区域,用于临时存储输入或输出的数据,以提高处理速度。...

    输入输出专题

    缓冲区在提高输入输出效率中起着关键作用,例如,`scanf`和`printf`默认使用缓冲区,而`getchar`和`putchar`则不。此外,有效的错误处理是确保程序健壮性的必要手段,例如,当文件无法打开或读写时应如何优雅地处理...

    在输入输出字符串时scanf(),printf()和gets(),puts()的区别浅谈

    总结一下,`scanf()`和`gets()`之间的主要区别在于处理空格和换行符的方式,以及是否清理输入缓冲区;`printf()`和`puts()`的区别在于是否自动添加换行。在编写程序时,选择合适的函数取决于你的需求,是否需要处理...

    编程语言-你想知道的编程语言(输入输出)

    例如,在C语言中,`scanf`和`getchar`共享缓冲区。 ##### 10. 输入输出的返回值 - **C语言**:`printf`返回输出的字节数,`scanf`返回成功读取的变量数量。 - **其他语言**:C++、C#和Python等语言中的输入输出函数...

    C语言程序设计中键盘输入数据的方法研究.pdf

    gets()函数可以将键盘中输入的字符串放入到字符数组中,但是它可能会导致缓冲区溢出。 C语言程序设计中键盘输入数据的方法多样化,技术人员需要根据实际情况选择合适的方法来获取键盘输入数据,以提高软件编程人员...

    新加坡南洋理工大学 计算机工程 课程 5

    例如,使用 `scanf()` 或 `getchar()` 函数读取数据时,实际上是从此缓冲区中获取数据。 #### 六、fflush() 函数 `fflush()` 函数用于清除输入输出缓冲区。在某些情况下,需要使用 `fflush()` 来清除输入缓冲区中的...

Global site tag (gtag.js) - Google Analytics