理解C语言的输入缓冲区[转]

1.机理

你键盘输入了东西,而此时你又没有用程序去getchar她,请问这个时候你按的键的状态保存在何处?为什么你一会儿去getchar的时候能得到呢

(例子好举,你先做一个1分钟延迟,然后再getchar,会发现一分钟前按的东西会显示出来)

实际上是 输入设备->内存缓冲区->程序getchar

你按的键是放进缓冲区了,然后供程序getchar

你有没有试过按住很多键然后等一会儿会滴滴滴滴响,就是缓冲区满了,你后头按的键没有存进缓冲区.

2.getchar()和getch()

然后就可以给你讲了

getchar是回车以后才进缓冲区

getch是每次都进缓冲区

用你的程序来说(我怎么觉得应该是n不是/n)

其实你输入computer,没按回车之前, 运行都停止在

getchar()里头,根本没有进入循环,自然也没有运行printf

当你一按回车,才从getchar出来,然后以后因为键盘缓冲区里头有东西,就一个一个字符getchar出来了

想立刻回显,用getch就好了

2.scanf

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

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

说了这么多举几个例子:

#include <stdio.h>

int main()

{

char n1[10];

char n2[10];

scanf(“%s”,n1);

scanf(“%s”,n2);

printf(“n1=%s,n2=%s”,n1,n2);

}

输入:

hello回车

world回车

得到:

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

这里hello后面就是输入再多个回车,空格也不会被赋值到n2中的,因为他们只是分隔符.

如果输入:

hello回车

光标处(等待输入)

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

其实这时缓冲区里是有一个’n’被留下来的,程序改成这样:

#include <stdio.h>

int main()

{

char n1[10];

char n2[10];

char n3,n4;

scanf(“%s”,n1);

scanf(“%s”,n2);

printf(“n1=%s,n2=%s”,n1,n2);

n3=getchar();

printf(“%c”,n3);

//n4=getchar();

//printf(“%c”,n4);

}

输入:

hello回车

world回车

得到:

hello

world

n1=hello,n2=wolrd

光标处(程序结束)

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

hello

world

n1=hello,n2=wolrd

光标处(等待输入)

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

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

比如:

#include <stdio.h>

int main()

{

char n1[10];

char n2;

scanf(“%s”,n1);

scanf(“%c”,&n2);

printf(“n1=%s,n2=%d”,n1,n2);

}

输入:

hello回车

得到:

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

如果输入:

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

得到:

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只要是通过缓冲区输入数据的函数都是等待回车键’r’出现才进入缓冲区的.再来个整型数据,字符串,字符的混合例子:

#include <stdio.h>

int main()

{

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);

}

输入:

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>

main(){

int a;

char ch;

scanf(“%d”,&a);

ch=getchar();

printf(“%d,%c”,a,ch);

}

输入:

95回车

得到:

95,

光标处(程序结束)

很明显这是由于分隔符(回车)被getchar读取并输出了,如果加入一句:getchar();

#include <stdio.h>

main(){

int a;

char ch;

scanf(“%d”,&a);

getchar();

ch=getchar();

printf(“%d,%c”,a,ch);

}

输入:

95回车

c回车

得到:

95,c光标处(程序结束)