示例代码:
int i;
char word [10][15];
for (i = 0; i < 10; i++){
fgets(word[i], 16, stdin);
}
所以我接受(最多)10个字符串用户输入,每个字符串的长度不能超过15个字符(因此\n
存储在fgets()
的最后一个字符位置abcdefghijklmnopqrstuvwxyz
1}}方法,对吗?)。
我的问题是当我想打印出单词数组中的单词时。发生这种情况:
输入:
abcdefghijklmnopqrstuvwxyz
pqrstuvwxyz
输出:
fgets()
我不知道为什么会这样。似乎 int j;
for (j = 0; j < 10; j++){
printf("%s", word[j]);
}
在输入15个字符后不会停止。
编辑:
{{1}}
答案 0 :(得分:3)
请记住,在C编程语言中,每个字符串都以尾随\0
字节终止。 fgets
函数最多只读取一个字符,而不是允许它写入缓冲区,因此它可以使用\0
字节终止缓冲区中的字符串。现在,在您的代码中,您允许fgets
在word
中写入比char[15]
中的每个word
多一个字节。最初,word
数组如下所示:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...
^ ^ ^
word[0] word[1] word[2]
其中?
代表未定义的值。在您的代码首次调用fgets
后,words
看起来像这样:
a b c d e f g h i j k l m n o \0? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...
^ ^ ^
word[0] word[1] word[2]
观察fgets
写的字节多于words[0]
中的空格,因此写入属于word[1]
的空格。但是,如果您要打印word[0]
printf
的内容,则字符abcdefghijklmno
将打印为printf
打印,直到遇到\0
字节为止。现在看看第二次调用word
后fgets
看起来的样子:
a b c d e f g h i j k l m n o p q r s t u v w x y z \n\0? ? ? ? ? ? ...
^ ^ ^
word[0] word[1] word[2]
在此调用中,fgets
不会超出word[1]
的末尾,因为它之前遇到换行符(\n
)。注意\0
中字符串的尾随word[0]
字节已被覆盖,因为该字符串进入word[1]
占用的内存区域。
现在如果你打印会发生什么?对printf
的第一次调用开始以a
开头打印,直到遇到\0
字符。这会导致打印字符串abcdefghijklmnopqrstuvwxyz\n
,因为\0
离开后没有o
个字节。 printf
的第二次调用从word[1]
开始,p
开始,直至看到\0
,导致pqrstuvwxyz\n
被打印。
现在你如何解决这个问题?要么让数组中的每个字符串更长一段,要让fgets
只读取15
而不是16
个字符。