C编程对fgets()函数字符的限制



示例代码:

    int i;
    char word [10][15];
    for (i = 0; i < 10; i++){
      fgets(word[i], 16, stdin);
    }

所以我接受(最多)10个字符串用户输入,每个字符串的长度不能超过15个字符长(因此是16个字符,因为n存储在fgets()方法的最后一个字符位置,对吧?)。

我的问题是当我想打印出单词数组中的单词时。发生这种情况:

输入:

abcdefghijklmnopqrstuvwxyz

输出:

abcdefghijklmnopqrstuvwxyz
pqrstuvwxyz

我不知道为什么会发生这种事。fgets()似乎在输入15个字符后不会停止。

编辑:

    int j;
    for (j = 0; j < 10; j++){
      printf("%s", word[j]);
    }
请记住,在C编程语言中,每个字符串都以一个尾随的字节结尾。fgets函数读取的字符最多比允许它写入缓冲区的字符少一个,因此它可以用字节终止缓冲区中的字符串。现在,在您的代码中,您允许fgetsword中写入比word中的每个char[15]多一个字节的内容。最初,word阵列看起来是这样的:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...
^                             ^                             ^
word[0]                       word[1]                       word[2]

其中CCD_ 12代表未定义的值。在您的代码第一次调用fgets之后,words看起来像这样:

a b c d e f g h i j k l m n o ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ...
^                             ^                             ^
word[0]                       word[1]                       word[2]

观察到fgetswords[0]中的空间多写了一个字节,因此它写入了属于word[1]的空间。然而,如果要用printf打印word[0]的内容,则字符串abcdefghijklmno将打印为printf打印,直到它遇到字节。现在看看第二次调用fgets:后word是什么样子

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? ? ? ? ? ? ...
^                             ^                             ^
word[0]                       word[1]                       word[2]

在这个调用中,fgets不会写超过word[1]的末尾,因为它之前遇到了换行符(n)字节。注意,word[0]中的字符串的尾部字节已被覆盖,因为该字符串进入了word[1]占用的内存区域。

现在,如果打印会发生什么?对printf的第一个调用从a开始打印,直到遇到字符。这导致字符串abcdefghijklmnopqrstuvwxyzn被打印,因为在剩下的o之后没有字节。printf的第二次调用从word[1]开始,在p开始,直到它看到,导致打印pqrstuvwxyzn

现在你怎么解决这个问题?使数组中的每个字符串都长一个,或者让fgets只读取15而不是16字符。

最新更新