当我们定义一个字符数组为'char name[10]'时,这表明数组'name'可以容纳一个长度为10个字符的字符串。但是在下面的程序中,数组名可以容纳十个以上的字符。这怎么可能?
//print the name of a person.
char name[10];
scanf("%s",name);
printf("%s",name);
在这里,如果我输入一个长度超过 10 个字符的名称,则不会出现运行时错误,程序会打印出我输入的所有字符。 如果我输入二十个或更多字符的名称,程序将终止。
注意:我在 Ubuntu9.04 上使用 gcc 编译器运行该程序。
最佳答案
因为scanf不知道数组有多长。变量“名称”不是“数组”类型,而是“指针”(或“地址”)类型。它说,从这里开始写,一直写到写完为止。你可能很幸运,你的堆栈上有一些其他不那么重要的东西被覆盖了,但最终,scanf 会写入和写入并覆盖一些致命的东西,你会得到一个段错误。这就是为什么您必须始终传递数组大小的原因。
这类似于给盲人一支铅笔并说“从这里开始写”,而他们却看不到纸的尽头在哪里。他们最终会在 table 上写字并损坏某些东西。 (注:这不是敲瞎子,这只是一个比喻。)
在上述情况下,我强烈建议使用 fgets() 从 stdin 获取特定数量,然后使用 sscanf() 从该行提取任何信息,并根据需要将其放入单独的变量中。 Scanf() 和 fscanf() 是邪恶的,我从来没有发现 fgets()+sscanf() 不能更安全地解决它们的用途。
char line[1024]; /* arbitrary size */
if( fgets( line, 1024, stdin ) != NULL )
{
fprintf( stdout, "Got line: %s", line );
}
或者对于字符串之外的东西:
# cat foo.c
#include <stdio.h>
int main( int argc, char **argv )
{
int i;
char line[1024];
while( fgets( line, 1024, stdin ) != NULL )
{
if( sscanf( line, "%d", &i ) == 1 )
{ /* 1 is the number of variables filled successfully */
fprintf( stdout, "you typed a number: %d\n", i );
}
}
}
# gcc foo.c -o foo
# ./foo
bar
2
you typed a number: 2
33
you typed a number: 33
<CTRL-D>
关于C 中的字符数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3224124/