【问题标题】:fgets reading more char than it shouldfgets 读取的 char 超出了应有的范围
【发布时间】:2016-05-29 17:25:17
【问题描述】:

我正在开发一个代码,用户将键入几个段落,当用户以“END”开始一个段落时,它将停止阅读。该代码将通过计算每个字母并显示图表和等等来操纵字符串,但这与问题无关。 问题是:哪个段落必须不超过 1000 个字符。

代码的较小版本如下(考虑到我只想存储 5 个字符的字符串 - 即使我会扩展它)。

#include <stdio.h>
#include <string.h>

int main()
{
  char paragraph[5];

  for ( ; ; )
  {
    fgets(paragraph, 5, stdin);

    if (paragraph[0]=='E' && paragraph[1]=='N' && paragraph[2]=='D')
    { return 0; }

    printf("%s", paragraph);
  }

  return 0;

我的问题是:如果我输入超过 5 个字符,printf 函数仍然打印超过 5 个字符,我不知道为什么。我已经检查了所有可能检查的内容。

请帮助像我这样的初学者。

【问题讨论】:

  • 您的printf 不打印换行符或类似内容,因此您将读取五个字符,打印它们,然后读取另外五个字符并立即打印它们。您一次阅读 5 次,只是您多次阅读。尝试在%s 之前打印一个字符以验证是否是这种情况。
  • “我已经检查了所有可能检查的内容。” - 除了来自fgets 的返回值。
  • 它输入超过 5 个字符,因为 fgets 不会丢弃该行的其余部分:它读取 all 输入。
  • 我已经检查过了,在我的知识范围内*

标签: c arrays string sizeof fgets


【解决方案1】:

fgets() 从流中最多读入一个小于 size 的字符,并且 将它们存储到 s 指向的缓冲区中。阅读停止后 EOF 或换行符。如果读取了换行符,则将其存储到缓冲区中。 终止空字节('\0')存储在最后一个字符之后 缓冲区。

因此,当输入超过 4 个字符(包括换行符)时,只会读取 4 个,其余的留在缓冲区中,准备下次读取fgets

您的printf 在这种情况下不会打印任何换行符,并且会被多次调用,看起来像是打印了超过 4 个字符。

按照 cmets 中的建议,尝试使用 printf("[%s]", paragraph); 查看各个 printf 调用。

【讨论】:

  • 是的,我尝试打印“%s\n”,现在我看到了。但现在我不知道两件事:(1)如何摆脱我不想要的剩余字符和(2)如果我的数组只有 5 个位置,我怎么可能打印超过 5 个字符。天啊……也许编码并不适合所有人,或者我很愚蠢。
  • 1) 见c-faq.com/stdio/stdinflush2.html。 2)多次打印或增加数组大小并读入数组中的下一个位置。希望它有所帮助,继续卡车运输。
【解决方案2】:

你应该在 string.h 中使用 strstr,因为它更简洁。

if (strstr(paragraph, "END"))
 return 0;

而不是

if (paragraph[0]=='E' && paragraph[1]=='N' && paragraph[2]=='D')
 return 0;  

【讨论】:

    【解决方案3】:

    尝试以下列方式修改您的代码,您将立即看到当您输入的字符多于缓冲区的size 时,fgets() 函数实际发生了什么。它不是从键盘读取,而是从stdinbuffer 读取。这些 SO 帖子也可能会让您感兴趣:(1)(2)。享受演示并确保通读man 页面。

    #include <stdio.h>
    
    int main()
    {
      char paragraph[5];
    
      for ( ; ; )
      {
        printf("Enter the string: \n\t");
    
        if(fgets(paragraph, 5, stdin) != NULL)
            printf("%s\n", paragraph);
    
        if (paragraph[0]=='E' && paragraph[1]=='N' && paragraph[2]=='D')
            return 0;    
      }
      return 0;
    }
    

    【讨论】:

    • 但是我怎样才能只打印 5 个字符呢?这似乎很容易,但我就是做不到。顺便说一句,字符存储在哪里?如果我的数组只有 5 个位置,printf 函数如何打印超过 5 个字符?
    • 请运行此演示,您将立即查看代码中的问题所在。另外,看看@Nightcrawler 的答案。
    猜你喜欢
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2012-02-15
    • 1970-01-01
    • 2015-10-23
    • 2019-10-24
    • 1970-01-01
    相关资源
    最近更新 更多