http://furzoom.com/c-language-gets-scanf/
2015
scanf()与gets()说明
scanf()函数和gets()函数都可用于输入字符串,当把它们用于输入字符串时,在功能上是有区别的。 在scanf()中使用%s
参数读取字符串时,其忽略开头部分的空格和TAB字符,直到遇到空格、TAB字符或者换行字符\n结束。并将结尾处的空格、TAB字符或者换行字符\n保存在缓冲区。其在读取的字符串后自动添加\0。 gets()函数从头开始读取直到遇到换行字符\n结束,会读入最后的换行字符,并将其转化为\0。
如下函数使用scanf函数读入2个字符串,接着用gets函数读入2个字符串,最后将4个字符串依次输出:
001 | <br /> /* Function foo() - By furzoom @ Mar 17, 2015 */ <br />#include<br /> void foo( void )<br />{<br /> char str1[10], str2[10], str3[10], str4[10];<br /> scanf ( "%s%s" , str1, str2);<br /> gets (str3);<br /> gets (str4);<br /><br /> puts (str1);<br /> puts (str2);<br /> puts (str3);<br /> puts (str4);<br />}<br /> |
输入如下内容:
001 | <br />aa bb<br />cc dd <br /> |
输出为:
001 | <br />aa<br />bb<br /><br />cc dd <br /> |
如期望的一样。其中str3读入的是上一次调用scanf时留在缓冲区的换行字符。
上面的演示代码是有问题的,如果输入的字符串长度大于10会是什么结果,程序一般情况下并不会给出任何提示,如果是特意设计好的输入字符串就是有非常严重的安全问题了。还好在GNU下编译会给出如下的警告:
warning: the `gets' function is dangerous and should not be used.
解决的办法就是使用fgets()函数替换gets()函数,指明最大的输出字符数。
如下程序,定义了1个整数和1个长度为4的字符数组,读取字符串后,输出整数和字符串:
001 | <br /> void foo( void )<br />{<br /> int num;<br /> char str[4];<br /> num = 0;<br /><br /> printf ( "%p\n%p\n" , &num, str);<br /> gets (str);<br /> printf ( "num:%d\n" , num);<br /> puts (str);<br />}<br /> |
编译运行结果如下所示:
001 | <br />0x7fffc7bfb8ec<br />0x7fffc7bfb8e0<br />aaaabbbbcccca<br />num:97<br />aaaabbbbcccca<br /> |
第3行为输入字符串。程序在64位的CentOS下gcc 4.4.7下编译运行。结果显示num的值被改变为97,这正是字符a的ASCII的值。具体的分析需要内存对齐和数在内存中存储方式有知识。该例子主要是为了证明gets()函数是很危险的。
参考链接:[1] http://leoenglish.blog.163.com/blog/static/1750319852011296336486/
[2] http://wenku.baidu.com/link?url=Vpd37wGuOwNPXgUp7y3LZ7vHSjWKGxg1gefoy_hQRHKBUr3oeoMCqM8fgwuOM5Wxgk-bSjUtsPLmswV7NAi27NWUwbY48LrVIQUv63MNsGC (完)
联系客服