C语言中gets()和scanf()的区别

C/C++ 2015年03月18日

C语言C++语言

scanf()与gets()说明

scanf()函数和gets()函数都可用于输入字符串,当把它们用于输入字符串时,在功能上是有区别的。 在scanf()中使用%s参数读取字符串时,其忽略开头部分的空格和TAB字符,直到遇到空格、TAB字符或者换行字符\n结束。并将结尾处的空格、TAB字符或者换行字符\n保存在缓冲区。其在读取的字符串后自动添加\0。 gets()函数从头开始读取直到遇到换行字符\n结束,会读入最后的换行字符,并将其转化为\0。

演示

如下函数使用scanf函数读入2个字符串,接着用gets函数读入2个字符串,最后将4个字符串依次输出:

<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 />

输入如下内容:

<br />aa bb<br />cc dd<br />

输出为:

<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的字符数组,读取字符串后,输出整数和字符串:

<br />void foo(void)<br />{<br />    int num;<br />    char str[4];<br />    num = 0;<br /><br />    printf("%p\n%p\n", &amp;num, str);<br />    gets(str);<br />    printf("num:%d\n", num);<br />    puts(str);<br />}<br />

编译运行结果如下所示:

<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 (完)

如无特别说明,本站文章皆为原创,若要转载,务必请注明以下原文信息:
日志标题:《C语言中gets()和scanf()的区别》
日志链接:http://furzoom.com/c-language-gets-scanf/
博客名称:枫竹梦

发表评论

插入图片

NOTICE1:请申请gravatar头像,没有头像的评论可能不会被回复!

回到顶部