﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-c++学习心得-文章分类-c++primer学习心得</title><link>http://www.cppblog.com/zhangzheyuk/category/12664.html</link><description>i love c++!</description><language>zh-cn</language><lastBuildDate>Tue, 03 Apr 2012 02:58:39 GMT</lastBuildDate><pubDate>Tue, 03 Apr 2012 02:58:39 GMT</pubDate><ttl>60</ttl><item><title>深入了解scanf()/getchar()和gets()等函数 </title><link>http://www.cppblog.com/zhangzheyuk/articles/145914.html</link><dc:creator>zzy</dc:creator><author>zzy</author><pubDate>Sat, 07 May 2011 13:47:00 GMT</pubDate><guid>http://www.cppblog.com/zhangzheyuk/articles/145914.html</guid><wfw:comment>http://www.cppblog.com/zhangzheyuk/comments/145914.html</wfw:comment><comments>http://www.cppblog.com/zhangzheyuk/articles/145914.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/zhangzheyuk/comments/commentRss/145914.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/zhangzheyuk/services/trackbacks/145914.html</trackback:ping><description><![CDATA[<p><font color="#ff1111" size="3">C/C++学习笔记1 - 
深入了解scanf()/getchar()和gets()等函数<br /></font><font color="#0000ff"><font size="2">----------------------------------------------------<br />| 
问题描述一：（分析scanf()和getchar()读取字符）&nbsp;&nbsp; 
|<br />----------------------------------------------------</font><br /></font>&nbsp;&nbsp;&nbsp; 
scanf(), 
getchar()等都是标准输入函数，一般人都会觉得这几个函数非常简单，没什么特殊的。但是有时候却就是因为使用这些函数除了问题，却找不出其中的原因。下面先看一个很简单的程序：<br /><font color="#cc33cc"><strong>程序1：</strong><br /></font>&nbsp;&nbsp;&nbsp; #include 
&lt;stdio.h&gt;<br />&nbsp;&nbsp;&nbsp; int main()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;char ch1, ch2;<br />&nbsp;scanf("%c", 
&amp;ch1); <br />&nbsp;scanf("%c", &amp;ch2);<br />&nbsp;printf("%d&nbsp; %d\n", ch1, 
ch2);<br />&nbsp;return 0;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;<strong> 或者是：</strong><br />&nbsp;&nbsp;&nbsp; #include 
&lt;stdio.h&gt;<br />&nbsp;&nbsp;&nbsp; int main()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;char ch1, ch2;<br />&nbsp;ch1 = 
getchar();<br />&nbsp;ch2 = getchar();<br />&nbsp;printf("%d&nbsp; %d\n", ch1, ch2);<br />&nbsp;return 
0;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; 
程序的本意很简单，就是从键盘读入两个字符，然后打印出这两个字符的ASCII码值。可是执行程序后会发现除了问题：当从键盘输入一个字符后，就打印出了 
结果，根本就没有输入第二个字符程序就结束了。例如用户输入字符'a', 打印结果是97，10。这是为什么呢？<br />【分析】：<br />&nbsp;&nbsp;&nbsp; 
首先我们呢看一下输入操作的原理， 
程序的输入都建有一个缓冲区，即输入缓冲区。一次输入过程是这样的，当一次键盘输入结束时会将输入的数据存入输入缓冲区，而cin函数直接从输入缓冲区中 
取数据。正因为cin函数是直接从缓冲区取数据的，所以有时候当缓冲区中有残留数据时，cin函数会直接取得这些残留数据而不会请求键盘输入，这就是例子 
中为什么会出现输入语句失效的原因！<br />&nbsp;&nbsp;&nbsp; 
其实这里的10恰好是回车符！这是因为scanf()和getchar()函数是从输入流缓冲区中读取值的，而并非从键盘(也就是终端)缓冲区读取。而读 
取时遇到回车(\n)而结束的，这个\n会一起读入输入流缓冲区的，所以第一次接受输入时取走字符后会留下字符\n，这样第二次的读入函数直接从缓冲区中 
把\n取走了，显然读取成功了，所以不会再从终端读取！这就是为什么这个程序只执行了一次输入操作就结束的原因！</p>
<p><font color="#0000ff" size="2">----------------------------------------------------<br />|&nbsp; 
问题描述二：（分析scanf()和gets()读取字符串）&nbsp;&nbsp; 
|<br />----------------------------------------------------</font><br />首先我们看一下scanf()读取字符串的问题：<br /><font color="#b32bd5">程序2：<br /></font>&nbsp;&nbsp;&nbsp; #include &lt;stdio.h&gt;<br />&nbsp;&nbsp;&nbsp; int 
main()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;char str1[20], str2[20];<br />&nbsp;scanf("%s",str1); 
<br />&nbsp;printf("%s\n",str1);&nbsp;&nbsp;&nbsp; <br />&nbsp;scanf("%s",str2);&nbsp; <br />&nbsp;printf("%s\n",str2);&nbsp; 
<br />&nbsp;return 0;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; 
程序的功能是读入一个字符串输出，在读入一个字符串输出。可我们会发现输入的字符串中不能出现空格，例如：<br /><font style="background-color: #6be61a"><em><u>测试一输入：</u></em><br /></font>Hello 
world!<br /><u><em><font style="background-color: #42e61a" color="#000000">输出：<br /></font></em></u>Hello<br />world!<br />【分 
析】到此程序执行完毕，不会执行第二次的读取操作！这个问题的原因跟问题一类似，第一次输入Hello world!后，字符串Hello 
world!都会被读到输入缓冲区中，而scanf()函数取数据是遇到回车、空格、TAB就会停止，也就是第一个scanf()会取出"Hello"， 
而"world!"还在缓冲区中，这样第二个scanf会直接取出这些数据，而不会等待从终端输入。</p>
<p><font style="background-color: #48dd22">测试二：</font><br />Hello[Enter] 
<br />Hello[输出]<br />world[Enter]<br />world[输出]<br />【分析】程序执行了两次从键盘读入字符串，说明第一次输入结束时的回车符被丢弃！即：scanf()读取字符串会舍弃最后的回车符！</p>
<p><br />我们再看一下gets()读取字符串的情况：<br />用scanf来读取一个字符串时，字符串中是不可以出现空格的，一旦出现空格，后面的数据就会舍弃残留在缓冲区中。其实有另外一个函数是可以接受空格的，那就是gets()，下面我们看一下这个函数的应用，我们把程序2改动一下：<br /><font color="#f709f7">程序3：<br /></font>#include &lt;stdio.h&gt;<br />int 
main()<br />{<br />&nbsp;char str1[20], str2[20];<br />&nbsp;gets(str1); 
<br />&nbsp;printf("%s\n",str1);&nbsp;&nbsp;&nbsp; <br />&nbsp;gets(str2);&nbsp; <br />&nbsp;printf("%s\n",str2);&nbsp; 
<br />&nbsp;return 0;<br />}<br /><font style="background-color: #48dd22">测试：</font><br />Hello world! 
[输入]<br />Hello world! [输出]<br />12345 [输入]<br />12345 
[输出]<br />【分析】显然与上一个程序的执行情况不同，这次程序执行了两次从键盘的读入，而且第一个字符串取了Hello world! 
接受了空格符，而没有像上一个程序那样分成了两个字符串！所以如果要读入一个带空格符的字符串时因该用gets(), 而不宜用scanf()!</p>
<p><br /><font color="#0000ff" size="2">--------------------------------------------------------<br />| 
问题描述三：（getchar()暂停程序，查看程序执行结果）|<br /></font><font color="#0000ff" size="2">--------------------------------------------------------<br /></font>&nbsp;&nbsp;&nbsp; 
不知道大家有没有遇到过这样的问题，有的编译器程序执行完后的结果界面不会停下而是一闪就没了，以至于看不到执行结果。所以很多人在程序最后加上 
getchar()语句，目的是想让程序执行完后停下来，等待从终端接收一个字符再结束程序。可是发现有时候这样根本没用，程序照样跳出去了。这是为什么 
呢？<br />【分析】原因跟上面例子讲的一样，是因为输入缓冲区中还有数据，所以getchar()会成果读到数据，所以就跳出了！</p>
<p><font color="#ff0000" size="2">------------------<br />|&nbsp;&nbsp;&nbsp;&nbsp; 【总结】&nbsp;&nbsp;&nbsp; 
|<br />------------------</font><br /><strong>第一：</strong>要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!<br />读取字符时：<br />scanf()以Space、Enter、Tab结束一次输入，不会舍弃最后的回车符（即回车符会残留在缓冲区中）；<br />getchar()以Enter结束输入，也不会舍弃最后的回车符；<br />读取字符串时：<br />scanf()以Space、Enter、Tab结束一次输入<br />gets()以Enter结束输入（空格不结束），接受空格，会舍弃最后的回车符！</p>
<p><strong>第二：</strong>为了避免出现上述问题，必须要清空缓冲区的残留数据，可以用以下的方法解决：<br />方法1：C语言里提供了函数清空缓冲区，只要在读数据之前先清空缓冲区就没问题了！<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
这个函数是fflush(stdin)。<br />方法2：自己取出缓冲区里的残留数据。<br />（说实话这个语句我也没看懂，呵呵！为什么格式控制是这样的！希望高手指点一下！）<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
scanf("%[^\n]",string);</p>
<p>&nbsp;</p>
<p>-------------------------------------------------------------------------------------------------------------------------</p>
<p>原文地址： <a href="http://hi.baidu.com/kskr/blog/item/cb00cc3deadf45c49f3d6279.html" target="_blank">hi.baidu.com/kskr/blog/item/cb00cc3deadf45c49f3d6279.html</a></p>
<p><span style="color: #ff0000"><strong>cin、cin.get()、cin.getline()、getline()、gets()等函数的用法</strong></span></p>
<p>学C++的时候，这几个输入函数弄的有点迷糊；这里做个小结，为了自己复习，也希望对后来者能有所帮助，如果有差错的地方还请各位多多指教（本文所有程序均通过VC 
6.0运行）转载请保留作者信息；<br />1、cin<br />1、cin.get()<br />2、cin.getline()<br />3、getline()<br />4、gets()<br />5、getchar()</p>
<p><strong><em><font color="#ff0000">1、cin&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
</font></em></strong></p>
<p><font color="#808000">用法1：最基本，也是最常用的用法，输入一个数字：</font></p>
<p><font color="#808080">#include &lt;iostream&gt;<br />using namespace std;<br />main 
()<br />{<br />int 
a,b;<br />cin&gt;&gt;a&gt;&gt;b;<br />cout&lt;&lt;a+b&lt;&lt;endl;<br />}</font></p>
<p>输入：2[回车]3[回车]<br />输出：5</p>
<p><font color="#808000">用法2：接受一个字符串，遇&#8220;空格&#8221;、&#8220;TAB&#8221;、&#8220;回车&#8221;都结束</font></p>
<p><font color="#808080">#include &lt;iostream&gt;<br />using namespace std;<br />main 
()<br />{<br />char 
a[20];<br />cin&gt;&gt;a;<br />cout&lt;&lt;a&lt;&lt;endl;<br />}</font></p>
<p>输入：jkljkljkl<br />输出：jkljkljkl</p>
<p>输入：jkljkl jkljkl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#808080">//遇空格结束</font><br />输出：jkljkl</p>
<p><em><strong><font color="#ff0000">2、cin.get()</font></strong></em></p>
<p>&nbsp;</p>
<p><font color="#808000">用法1： cin.get(字符变量名)可以用来接收字符</font></p>
<p><font color="#808080">#include &lt;iostream&gt;<br />using namespace std;<br />main 
()<br />{<br />char ch;<br />ch=cin.get();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
//或者cin.get(ch);<br />cout&lt;&lt;ch&lt;&lt;endl;<br />}</font></p>
<p>输入：jljkljkl<br />输出：j</p>
<p><font color="#808000">用法2：cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格</font></p>
<p><font color="#808080">#include &lt;iostream&gt;<br />using namespace std;<br />main 
()<br />{<br />char 
a[20];<br />cin.get(a,20);<br />cout&lt;&lt;a&lt;&lt;endl;<br />}</font></p>
<p>输入：jkl jkl jkl<br />输出：jkl jkl jkl</p>
<p>输入：abcdeabcdeabcdeabcdeabcde （输入25个字符）<br />输出：abcdeabcdeabcdeabcd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
（接收19个字符+1个'\0'）</p>
<p><font color="#808000">用法3：cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.</font><font color="#808000"> </font></p>
<p>这个我还不知道怎么用，知道的前辈请赐教；</p>
<p><strong><em><font color="#ff0000">3、cin.getline()&nbsp;&nbsp; // 
接受一个字符串，可以接收空格并输出</font></em></strong></p>
<p><font color="#808080">#include &lt;iostream&gt;<br />using namespace std;<br />main 
()<br />{<br />char 
m[20];<br />cin.getline(m,5);<br />cout&lt;&lt;m&lt;&lt;endl;<br />}</font></p>
<p>输入：jkljkljkl<br />输出：jklj</p>
<p>接受5个字符到m中，其中最后一个为'\0'，所以只看到4个字符输出；</p>
<p><font color="#808080">如果把5改成20：<br /></font><font color="#808080">输入：jkljkljkl<br />输出：jkljkljkl</font></p>
<p><font color="#808080">输入：jklf fjlsjf fjsdklf<br />输出：jklf fjlsjf 
fjsdklf</font></p>
<p>//延伸：<br />//cin.getline()实际上有三个参数，cin.getline(接受字符串的看哦那间m,接受个数5,结束字符)<br />//当第三个参数省略时，系统默认为'\0'<br />//如果将例子中cin.getline()改为cin.getline(m,5,'a');当输入jlkjkljkl时输出jklj，输入jkaljkljkl时，输出jk</p>
<p>当用在多维数组中的时候，也可以用cin.getline(m[i],20)之类的用法：</p>
<p><font color="#808080">#include&lt;iostream&gt;<br />#include&lt;string&gt;<br />using 
namespace std;</font></p>
<p><font color="#808080">main ()<br />{<br />char m[3][20];<br />for(int 
i=0;i&lt;3;i++)<br />{<br />cout&lt;&lt;"\n请输入第"&lt;&lt;i+1&lt;&lt;"个字符串："&lt;&lt;endl;<br />cin.getline(m[i],20);<br />}</font></p>
<p><font color="#808080">cout&lt;&lt;endl;<br />for(int 
j=0;j&lt;3;j++)<br />cout&lt;&lt;"输出m["&lt;&lt;j&lt;&lt;"]的值:"&lt;&lt;m[j]&lt;&lt;endl;</font></p>
<p><font color="#808080">}</font></p>
<p>请输入第1个字符串：<br />kskr1</p>
<p>请输入第2个字符串：<br />kskr2</p>
<p>请输入第3个字符串：<br />kskr3</p>
<p>输出m[0]的值:kskr1<br />输出m[1]的值:kskr2<br />输出m[2]的值:kskr3</p>
<p><em><strong><font color="#ff0000">4、getline()&nbsp;&nbsp;&nbsp;&nbsp; // 接受一个字符串，可<font color="#ff0000">以接收空格并输出，</font></font><font color="#ff0000">需包含&#8220;#include&lt;string&gt;&#8221;</font></strong></em></p>
<p><font color="#808080">#include&lt;iostream&gt;<br />#include&lt;string&gt;<br />using 
namespace std;<br />main ()<br />{<br />string 
str;<br />getline(cin,str);<br />cout&lt;&lt;str&lt;&lt;endl;<br />}</font></p>
<p>输入：jkljkljkl<br />输出：jkljkljkl</p>
<p>输入：jkl jfksldfj jklsjfl<br />输出：jkl jfksldfj jklsjfl</p>
<p>和cin.getline()类似，但是cin.getline()属于istream流，而getline()属于string流，是不一样的两个函数</p>
<p><font color="#ff0000"><strong><em>5、gets()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 
接受一个字符串，可以接收空格并输出，需包含&#8220;#include&lt;string&gt;&#8221;</em></strong></font></p>
<p><font color="#808080">#include&lt;iostream&gt;<br />#include&lt;string&gt;<br />using 
namespace std;<br />main ()<br />{<br />char m[20];<br />gets(m);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
//不能写成m=gets();<br />cout&lt;&lt;m&lt;&lt;endl;<br />}</font></p>
<p>输入：jkljkljkl<br />输出：jkljkljkl</p>
<p>输入：jkl jkl jkl<br />输出：jkl jkl jkl</p>
<p>类似cin.getline()里面的一个例子，gets()同样可以用在多维数组里面：</p>
<p><font color="#808080">#include&lt;iostream&gt;<br />#include&lt;string&gt;<br />using 
namespace std;</font></p>
<p><font color="#808080">main ()<br />{<br />char m[3][20];<br />for(int 
i=0;i&lt;3;i++)<br />{<br />cout&lt;&lt;"\n请输入第"&lt;&lt;i+1&lt;&lt;"个字符串："&lt;&lt;endl;<br />gets(m[i]);<br />}</font></p>
<p><font color="#808080">cout&lt;&lt;endl;<br />for(int 
j=0;j&lt;3;j++)<br />cout&lt;&lt;"输出m["&lt;&lt;j&lt;&lt;"]的值:"&lt;&lt;m[j]&lt;&lt;endl;</font></p>
<p><font color="#808080">}</font></p>
<p>请输入第1个字符串：<br />kskr1</p>
<p>请输入第2个字符串：<br />kskr2</p>
<p>请输入第3个字符串：<br />kskr3</p>
<p>输出m[0]的值:kskr1<br />输出m[1]的值:kskr2<br />输出m[2]的值:kskr3</p>
<p>自我感觉gets()和cin.getline()的用法很类似，只不过cin.getline()多一个参数罢了；</p>
<p>这里顺带说明一下，对于本文中的这个kskr1,kskr2,kskr3的例子，对于cin&gt;&gt;也可以适用，原因是这里输入的没有空 
格，如果输入了空格，比如&#8220;ks kr jkl[回车]&#8221;那么cin就会已经接收到3个字符串，&#8220;ks,kr,jkl&#8221;；再如&#8220;kskr 1[回车]kskr 
2[回车]&#8221;，那么则接收&#8220;kskr,1,kskr&#8221;；这不是我们所要的结果！而cin.getline()和gets()因为可以接收空格，所以不会产 
生这个错误；</p>
<p><strong><em><font color="#ff0000">6、getchar()&nbsp;&nbsp; //接受一个字符，需包含<font color="#ff0000">&#8220;</font></font><font color="#ff0000">#include&lt;string&gt;&#8221;</font></em></strong></p>
<p><font color="#808080">#include&lt;iostream&gt;<br />#include&lt;string&gt;<br />using 
namespace std;<br />main ()<br />{<br />char 
ch;<br />ch=getchar();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
//不能写成getchar(ch);<br />cout&lt;&lt;ch&lt;&lt;endl;<br />}</font></p>
<p>输入：jkljkljkl<br />输出：j</p>
<p>//getchar()是C语言的函数，C++也可以兼容，但是尽量不用或少用；</p><img src ="http://www.cppblog.com/zhangzheyuk/aggbug/145914.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/zhangzheyuk/" target="_blank">zzy</a> 2011-05-07 21:47 <a href="http://www.cppblog.com/zhangzheyuk/articles/145914.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>