【问题标题】:C, flushing stdinC、冲洗标准输入
【发布时间】:2011-04-22 00:34:32
【问题描述】:

我在使用 fget 时遇到问题。该循环应该读取一行最大值。 19 个字符,分析这个 char 数组,然后等待下一个输入。 问题是,如果输入的行超过 19 个字符,fgets 将用剩余的字符填充 str,直到输入 Ctrl-D 或换行符,从而在没有新输入的情况下启动一个新循环。输入(stdin)应该在读取 19 个字符后以某种方式刷新,因此循环可以从一个干净的状态开始。有没有人可以解决这个问题?

 char str[20];
 while((fgets(str, 20, stdin) != NULL)) {
  puts(str);        //monitoring str

  if(str[0] == 'q') break;
 }

使用示例:

hola hola                        //user inputs 9 chars + newline
hola hola                        //puts writes

hoo hoo hoo hoo hooh             //user inputs 20 chars + newline
hoo hoo hoo hoo hoo              //puts writes
h                                //

【问题讨论】:

    标签: c stdin


    【解决方案1】:

    scanf("%*[^\n]\n"); 可能是最简单的可能性之一。

    【讨论】:

    • 我想你必须传递一个字符缓冲区参数。此解决方案不检查缓冲区溢出,是吗?天哪,我的 C 太生锈了。
    • @xpmatteo :它不需要缓冲区参数。来自 man scanf:“可选的 '*' 赋值抑制字符:scanf() 按照转换规范的指示读取输入,但丢弃输入。不需要相应的指针参数”
    • 正如@Giuseppe 指出的那样,这样做的部分好处是您不必传递缓冲区。由于没有缓冲区,因此也不存在缓冲区溢出的可能性。不过不要因为没有意识到这一点而责怪自己:这种转换绝对是深奥的。
    • 您确实需要先检查fgets() 读取的字符串是否以\n 结束,否则您将读取并丢弃next 行。
    • 您可能希望使用"%*[^\n]%*c" 而不是"%*[^\n]\n"\n 不匹配文字换行符,而是丢弃任何数量的空白,直到下一个非空白字符。
    【解决方案2】:
    char str[21];  /* read one extra character */
    while (fgets(str, 21, stdin) != NULL) {
        /* if line too long, truncate and swallow the rest of the line */
        if (strlen(str) > 19) {
            str[19] = '\0';
            while (getchar() != '\n' && !feof(stdin))
                ;
        }
    
        puts(str);
        if(str[0] == 'q') break;
    }
    

    【讨论】:

      【解决方案3】:

      另一个可能的变体,约束 fgets() 是唯一使用的输入并且在循环级别。这绝对与 larsman 提出的非常相似。所以我想我会投票给他:-)

      #include <stdio.h>
      
      int main(){
          char str[20];
          int skip = 0;
          str[19] = 1;
          while (fgets(str, 20, stdin)) {
              // just ignore lines of more than 19 chars
              if (str[19] == 0){
                  str[19] = 1;
                  skip = 1;
                  continue;
              }
              // also skip the end of long lines
              if (skip) {
                  skip = 0;
                  continue;
              }
              // monitor input
              puts(str);
              // stop on any line beginning with 'q'
              if (str[0] == 'q'){
                  break;
              }
          };
      }
      

      【讨论】:

        【解决方案4】:

        看看 fpurge:

        fpurge(stdin);
        

        【讨论】:

          【解决方案5】:

          试试:

          fgets(str, 2000, stdin)
          

          然后将 str 截断为 19 :-)

          【讨论】:

          • ...希望用户永远不要粘贴 2 MB 长的行!
          • True :-) 但这是一个快速的解决方案。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-07
          • 1970-01-01
          • 2016-04-21
          • 1970-01-01
          • 1970-01-01
          • 2011-05-18
          • 1970-01-01
          相关资源
          最近更新 更多