【问题标题】:fgets() and weird characters in the end of the string, in Cfgets() 和字符串末尾的奇怪字符,在 C 中
【发布时间】:2020-06-25 10:44:22
【问题描述】:

我试图从 C 中的标准输入中获取一个字符串。所以我尝试使用最愚蠢的东西:

int main(){
      int j;
      char name[20];

   printf("Who are you? ");
   fgets(name,20,stdin);
   printf("Glad to meet you, %s",name);

      for(j=0;j<20;j=j+1){
          printf(" %d = %c\n  ", j, name[j]);
      }   
}

所有这些奇怪的字符都出现了:

    Who are you? Hana
Glad to meet you, Hana
   0 = H
   1 = a
   2 = n
   3 = a
   4 =

   5 =
   6 =  
   7 =  
   8 = Ŕ
   9 = ■
   10 = `
   11 =
   12 = Ý
   13 = o
   14 = 
   15 = v
   16 = P
   17 = 
   18 = @
   19 =

发生了什么?

【问题讨论】:

  • 数组没有初始化——它只是垃圾——不管这些内存位置发生了什么。在 C 中,您必须显式初始化本地(自动)变量。
  • 这很正常。您的数组最多可以容纳 20 个字符,但它不会全部使用它们。有效部分是直到第一个空字符 name[4] 在您的情况下的字符。其余的都是单元化的,但你通常不关心它们。 (这 20 个字符包括空字符,因此您的名称最多可以有 19 个字符,fgets 将确保这一点。)
  • printf 格式 %c 未正确显示终止 NUL 字符 ('\0')。使用例如printf(" %d = %c (%d)\n ", j, name[j], (int)name[i]); 来查看使终止 NUL 明显的字符代码。
  • @MOehm: name[4] == '\n' — 见印刷。 name[5] == '\0' 之后的内容就是垃圾。
  • @JonathanLeffler:是的,没错。错过了尾随的换行符。但是我的评论的编辑期已经结束,所以我会让我的错误保持不变......

标签: c string fgets


【解决方案1】:

当您输入字符 Hana 时,数组名称的六个元素得到以下值

{ 'H', 'a', 'n', 'a', '\n', '\0' }

注意:fgets 还会放置与按下的键 Enter 对应的换行符“\n”,如果目标字符数组有足够的空间来存储它。

数组名的所有其他元素都没有得到值。

要输出数组的实际值,不包括换行符和终止零,您可以编写

  for( j = 0; name[j] != '\n' && name[j] != '\0'; j++ ){
      printf(" %d = %c\n  ", j, name[j]);
  }  

【讨论】:

    【解决方案2】:

    没有什么不寻常的。字符串“Hana”存储在name 变量中。该字符串以 null 结尾,因此写入了 5 个字符:“H”、“a”、“n”、“a”和“\0”。缓冲区的其余部分保持不变。

    您不应该在缓冲区边界之外读取,但在缓冲区内,终止 '\0' 之后的所有内容都不会被触及。由于您没有初始化缓冲区,它可能包含任意数据。

    【讨论】:

    • 这是一个相当不错的描述,但您忽略了 fgets 保留的换行符。
    • 大部分是name[4] == '\n'name[5] == '\0'(当然没有写出来)。
    • OP 不会在数组边界之外读取。那是你的困惑。读取char 数组中的字符是有效的,不管它是否是字符串的内容。同样如前所述,写入 5 个字符是错误的,实际上读取换行符是 6 个。
    【解决方案3】:

    请注意,字符串不是char 数组。正确的字符串是直到第一个空字符的所有内容,它终止正确的字符串。

    数组,这里是name,是存储字符串的存储。字符串可能没有数组大小那么长,在您的示例中就是这种情况,但数组至少需要能够保存字符串(包括终止的\0)。

    fgets 输入的"hana" 仅占用name - hana\n\0 的前6 个字符。请注意,fgets 还会将按下的换行符附加到 Return 到正确的字符串中。

    name 中带有\0 的元素之后的字符元素未分配\0

    \0 之后打印的所有内容都是垃圾,因为由于name 不符合externstatic,因此内容未初始化。

    请注意,\n\0 不可打印
    人物。

    【讨论】:

      【解决方案4】:

      您可能没有正确初始化数组。另外,您不应该将指针传递给您打算使用的数组吗?

      【讨论】:

      • 您希望 OP 在哪里“传递指向数组的指针”?据我所知,函数调用中name 的所有使用都是正确的。
      • OP 绝对没有初始化数组根本
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 2017-08-18
      相关资源
      最近更新 更多