C语言中用scanf.docx
- 文档编号:30211130
- 上传时间:2023-08-07
- 格式:DOCX
- 页数:18
- 大小:24.23KB
C语言中用scanf.docx
《C语言中用scanf.docx》由会员分享,可在线阅读,更多相关《C语言中用scanf.docx(18页珍藏版)》请在冰豆网上搜索。
C语言中用scanf
C语言中用scanf()连续输入两个字符时的问题
#include
intmain()
{
charch1,ch2;
printf("Inputforch1:
\n");
scanf("%c",&ch1);
printf("ch1=%c\n",ch1);
printf("Inputforch2:
\n");
scanf("%c",&ch2);
printf("ch2=%c\n",ch2);
}
表面上看这段程序是没有错的,也可以运行,但运行过程中到第二个scanf输入值给ch2时,程序不会停止,而是直接运行到最后一个printf!
原来scanf是从标准输入缓冲区中读取输入的数据,而%c的字符输入格式会接收回车字符,在输入第一个scanf时输入字符后按回车结束,输入缓冲中保存了这个回车符,遇到第二个scanf时,它自动把这个回车符赋给了ch2。
而如果第二个scanf的输入格式不是%c时,由于格式不匹配,这个回车符会被自动忽略,所以只有在连续输入两个%c的格式时才会出现这样的问题!
解决办法:
1.清空输入缓冲区
第一个scanf后加入语句:
fflush(stdin); //C语言清空输入缓冲区函数
2.格式控制中加入空格
将第二个scanf改为:
scanf("%c",&ch2);//在%号前面加一个空格,空格可以抵消前面输入的回车符。
ps:
本题其实不用那么麻烦,scanf("%c%c",&ch1,&ch2);一句就可以搞定了,上面只是介绍下解决问题的方法。
scanf格式输入时要求输入格式与格式控制符中的完全一样,例如:
scanf("abcd%c",&ch);输入时必须输入abcde,ch得到的值才为e。
另外:
1.scanf("%d%d",&x,&y);时,输入必须为1020(注:
10和20之间要用空格,回车或TAB键之中的任选一种隔开)
2.scanf("%d,%d",&x,&y);时,输入必须为10,20
3.scanf("%d+%d",&x,&y);时,输入必须为10+20
为了您的安全,请只打开来源可靠的网址
打开网站 取消
来自:
c语言输入输出缓冲区的概念
(2008-05-1017:
09:
17)
转载▼
标签:
n2
缓冲区
n1
分隔符
回车符
it
分类:
C++教学
你肯定会奇怪为什么一开始先说这个,一开始不都是数据类型什么的嘛,这个写在最前面因为后面的程序即使最简单的code都会用到输入输出,输出比较简单,可以放在后面再说,但是输入就不同了,如果不先了解一下,可能会得到和你预想不同的结果哦^_^.也正是由于和一般的c语言介绍方式不同,为了看起来正规一些,我就把这章叫做chapter0了,完全可以先跳过去,直接看chapter1.
1.getchar
先引用一下前人的成果(有修改)^_^:
getchar()是stdio.h中的库函数,它的作用是从stdin流中读入一个字符,也就是说,如果stdin有数据的话不用输入它就可以直接读取了。
而getch()和getche()是conio.h中的库函数,它的作用是从键盘接收字符。
getchar带有显示。
与前面两个函数的区别在于:
getchar()函数等待输入直到按回车才结束(前提是缓冲区没有数据),回车前的所有输入字符都会逐个显示在屏幕上。
但只有第一个字符作为函数的返回值。
#include
#include
voidmain()
{
charc;
c=getchar();
//getchar()在这里它只返回你输入字符串的第一个字符,并把返回值赋值给c
putchar(c);
printf("\n\n");
}
这个程序你运行一下,相信你又会有疑问了。
这个就是从缓冲区中读取了例子。
第一次getchar()时,确实需要人工的输入,但是如果你输了多个字符,以后的getchar()再执行时就会直接从缓冲区中读取了。
#include
#include
voidmain()
{
charc;
while((c=getchar())!
='\n')
printf("%c",c);
printf("\n\n");
}
程序运行时,首先停下来,等你输入一串字符串,输入完毕后,它把你输入的整个字符串都输出来了,咦,你不是说getchar()只返回第一个字符么,这里怎么?
因为我们输入的字符串并不是取了第一个字符就把剩下的字符串丢掉了,它还在我们的内存中,就好比,开闸放水,我们把水放到闸里去以后,开一次闸就放掉一点,开一次就放掉一点,直到放光了为止,这里开闸动作就相当于调用一次getchar()。
我们输入的字符串也是这么一回事,首先我们输入的字符串是放在内存的缓冲区中的,我们调用一次getchar()就把缓冲区中里出口最近的一个字符输出,也就是最前面的一个字符输出,输出后,就把它释放掉了,但后面还有字符串,所以我们就用循环把最前面的一个字符一个个的在内存中释放掉,直到不满足循环条件退出为止。
例子中循环条件里的'\n'实际上就是你输入字符串后的回车符,所以意思就是说,直到遇到回车符才结束循环,而getchar()函数就是等待输入(或缓冲区中的数据)直到按回车才结束,所以实现了整个字符串的输出。
当然,我们也可以把循环条件改一下,比如while((c=getchar())!
='a'),什么意思呢,意思就是遇到字符'a'就停止循环,当然意思是如果你输入“12345a213123\n”那么只会输出到a,结果是12345a。
再次注意:
用getchar()它是从“流”中间去读取,所以第一个getchar()接受的是刚刚中断的流队列中即将出列的第一个字符(不限于回车符,上面举过例子了),如果流队列不为空,执行getchar()就继续放水,直到把回车符也放空为止,空了之后再在执行getchar()就停下等待你的输入了;我们用getch()为什么每次都是等待用户的输入呢?
因为getch()是从键盘接收,即时的接收,并不是从stdin流中去读取数据。
补充:
按键盘上的回车产生了2个字符:
回车符('\r')和换行符('\n')。
回车符'\r'(CR:
carriagereturn:
倒车)使光标回到这行的首部,换行符('\n')(newline)然后再换行。
所以当输入字符'w',并按下回车键以后。
首先得到回车符。
那个getchar函数结束了。
但是还存在一个换行符。
所以如果用getchar()来做判断的时候。
最好再写一次getchar()清除缓冲区的'\n'.
3.如何清空输入缓冲区的内容?
如果我想让getchar()每次都能够等待用户输入的话就要清空缓冲区,下面就介绍方法(不同平台)
C标准规定fflush()函数是用来刷新输出(stdout)缓存的。
对于输入(stdin),它是没有定义的。
但是有些编译器也定义了fflush(stdin)的实现,比如微软的VC。
其它编译器是否也定义了fflush(stdin)的实现应当查找它的手册。
GCC编译器没有定义它的实现,所以不能使用fflush(stdin)来刷新输入缓存。
对于没有定义fflush(stdin)的编译器,可以使用fgets()函数来代替它(比用getchar()、scanf()等函数通用性好)。
可以这样忽略输入流中留下的回车等其它输入,从而使下一次的输入总保持一个“干净”的状态。
(这个是任何平台下都可以的)
charsbuf[1024];
//...
fgets(sbuf,1024,stdin);
//...
在windows的vc下面就可以这样了:
for(inti=0;i<10;++i)
{
charch=getchar();
fflush(stdin);//每次都会有等待状态了
}
这里说到gcc编译器没有定义fflush的实现,我们一般用getchar();来清除缓冲区.
下面是我的讨论:
先来一段code:
#include
main()
{
charc;
for(;(c=getchar())!
='a';)
printf("%c",c);
getchar();
c=getchar();
printf("%c",c);
}
输入:
ssss回车
得到:
ssss
光标处(等待输入)
说明:
此时程序没有结束,进行到for循环,因为并没有字符a出现,所以还没跳出for循环.键入回车后,getchar
依次从缓冲区内取出(for循环):
's''s''s''s''\n'
如果我们输入:
ssssa回车
得到:
ssss光标处(等待输入)
说明:
程序已经跳出for循环,但是由于我们用getchar();清除了换行'\n',后面第7句c=getchar();需要你输入一个字符(因为ssssa后面并没有新的字符),所以程序仍然没有结束.如果我们注释掉getchar();这一句,那么得到:
ssss
光标处(程序结束)
这个输入ssssa是的回车中的换行符'\n'就被c=getchar();这一句读取并输出了。
总结:
键盘输入的字符都存到缓冲区内,一旦键入回车,getchar就进入缓冲区读取字符,一次只返回第一个字符作为getchar函数的值,如果有循环或足够多的getchar语句,就会依次读出缓冲区内的所有字符直到'\n'.要理解这一点,之所以你输入的一系列字符被依次读出来,是因为循环的作用使得反复利用getchar在缓冲区里读取字符,而不是getchar可以读取多个字符,事实上getchar每次只能读取一个字符.如果需要取消'\n'的影响,可以用getchar();来清除,这里getchar();只是取得了'\n'但是并没有赋给任何字符变量,所以不会有影响,相当于清除了这个字符.还要注意的是这里你在键盘上输入ssss看到的回显正是来自于getchar的作用,如果用getch就看不到你输入了什么.再引一篇文章:
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
intmain()
{
charn1[10];
charn2[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
intmain()
{
charn1[10];
charn2[10];
charn3,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
intmain()
{
charn1[10];
charn2;
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
intmain()
{
inta,b,c;
charn1[10];
charn2,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接受,这里用了回车,可以试一下空格)
45jfdkjfa(回车)
得到:
a=12,b=34,n2=
c=45,n1=jfdkjfa,n3=
光标处(程序结束)
这里说明一下过程:
在前两个整型数据输入时,两个数据之间无论是回车还是若干空格都被scanf当做分隔符,好了,scanf读到分隔符(回车或空格)时,把第一个整型数据送到变量a中,缓冲区中留下分隔符和下面的整型数据,这时scanf再读当然先读分隔符,但是要求输入的还是整型数据(%d),所以分隔符被忽略,如果这时要求输入字符%c(不是字符串%s),那么分隔符将以一个字节的形式送到字符变量里,就如同这里的n2.同理可以知道c和n1的保存过程,最后的n3正是接收了输入时的最后一个回车.
好了如果看到这里你都理解了那么看最后一个例子:
#include
main(){
inta;
charch;
scanf("%d",&a);
ch=getchar();
printf("%d,%c",a,ch);
}
输入:
95回车
得到:
95,
光标处(程序结束)
很明显这是由于分隔符(回车)被getchar读取并输出了,如果加入一句:
getchar();
#include
main(){
inta;
charch;
scanf("%d",&a);
getchar();
ch=getchar();
printf("%d,%c",a,ch);
}
输入:
95回车
c回车
得到:
95,c光标处(程序结束)
搞C30年的能读懂这段代码就是天才-C大师ianphillipps作品
请耐心将下边的故事看完:
OnthefirstdayofChristmasmytruelovegavetome
apartridgeinapeartree.
OntheseconddayofChristmasmytruelovegavetome
twoturtledoves
andapartridgeinapeartree.
OnthethirddayofChristmasmytruelovegavetome
threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OnthefourthdayofChristmasmytruelovegavetome
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OnthefifthdayofChristmasmytruelovegavetome
fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OnthesixthdayofChristmasmytruelovegavetome
sixgeesea-laying,fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OntheseventhdayofChristmasmytruelovegavetome
sevenswansa-swimming,
sixgeesea-laying,fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OntheeigthdayofChristmasmytruelovegavetome
eightmaidsa-milking,sevenswansa-swimming,
sixgeesea-laying,fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OntheninthdayofChristmasmytruelovegavetome
nineladiesdancing,eightmaidsa-milking,sevenswansa-swimming,
sixgeesea-laying,fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
andapartridgeinapeartree.
OnthetenthdayofChristmasmytruelovegavetome
tenlordsa-leaping,
nineladiesdancing,eightmaidsa-milking,sevenswansa-swimming,
sixgeesea-laying,fivegoldrings;
fourcallingbirds,threefrenchhens,twoturtledoves
andapartridgeinapeartree.
OntheeleventhdayofChristmasmytruelovegavetome
elevenpiperspiping,tenlordsa-leaping,
nineladiesdancing,eightmaidsa-milking,sevenswansa-swimming,
sixgeesea-laying,fivegoldrings;
fourc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 中用 scanf