关于fgets()函数字符限制的C编程?

时间:2015-03-24 22:31:33

标签: c char fgets

示例代码:

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

1 个答案:

答案 0 :(得分:3)

请记住,在C编程语言中,每个字符串都以尾随\0字节终止。 fgets函数最多只读取一个字符,而不是允许它写入缓冲区,因此它可以使用\0字节终止缓冲区中的字符串。现在,在您的代码中,您允许fgetsword中写入比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字节为止。现在看看第二次调用wordfgets看起来的样子:

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个字符。