【问题标题】:Using getchar() on c gets the 'Enter' after input [duplicate]在 c 上使用 getchar() 在输入后得到“Enter”[重复]
【发布时间】:2011-04-27 13:25:50
【问题描述】:

我正在尝试编写一个简单的程序,要求用户在循环中从菜单中进行选择。 我使用 getchar() 来获取输入,但是我注意到当我输入一个字符并按“Enter”时,程序会进行两个循环(好像我按了两次)一个字符作为输入,另一个用于“Enter”作为输入。

我该如何解决这个问题?

【问题讨论】:

    标签: c getchar


    【解决方案1】:

    最简单的方法是从getchar过滤掉回车键作为返回值

    char c = (char)getchar();
    if ( c != '\n' ) {
      ...
    }
    

    【讨论】:

    • 我猜你的意思是getchar()?如果是这样,getchar() 返回 int。
    • @Nyan, getchar 确实返回 int 但通过转换分配给 char 是合法的。参考cplusplus.com/reference/clibrary/cstdio/getchar
    • @Jared:是的,但是 char 被限制为(通常)256 个值,并且您需要(通常)257 个值来识别 ALL 个字符 AND EOF。这就是为什么 getchar() 返回一个 int
    • @pmg,我知道这一点。我只是在演示 OP 的要求(如何检查换行符)。
    • 好的,不过你也可以用int c 演示:-)
    【解决方案2】:

    您已经回答了自己的问题;你必须以某种方式处理换行符。

    有多种选择。如果您的菜单选项是编号,您可以使用scanf() 读取一个整数值并根据该值进行切换:

    printf("Pick an option: ");
    fflush(stdout);
    scanf("%d", &option);
    switch(option)
    {
      case 0 : do_something(); break;
      case 1 : do_something_else(); break;
      ...
      default: bad_option(); break;
    }
    

    此选项的优点是%d 转换说明符会跳过任何前导空格,包括换行符,因此您不必担心任何未读的\n 会阻塞输入流(事实上,大多数的转换说明符会跳过前导空格;%c 不会,这使得它的行为很像getchar())。

    此选项的缺点是,如果有人在其输入中粗指非数字字符,则不会使用 %d 转换说明符读取它,并且会一直停留在输入流中,直到调用getchar()scanf()%s%c 转换说明符。

    更好的选择是使用fgets() 将所有输入读取为字符字符串,然后根据需要进行解析和验证。

    /**
     * Prints a prompt to stdout and reads an input response, writing
     * the input value to option.  
     *
     * @param prompt [in]  - prompt written to stdout
     * @param option [out] - option entered by user
     *
     * @return - 1 on success, 0 on failure.  If return value is 0, then option
     * is not changed.
     */
    int getOption(const char *prompt, char *option)
    {
      char input[3]; // option char + newline + 0 terminator
      int result = 0;
    
      printf("%s: ", prompt);  
      fflush(stdout);
    
      if (fgets(input, sizeof input, stdin))
      {
        /**
         * Search for a newline character in the input buffer; if it's not
         * present, then the user entered more characters than the input buffer 
         * can store.  Reject the input, and continue to read from stdin until
         * we see a newline character; that way we don't leave junk in the
         * input stream to mess up a future read.
         */
        char *newline = strchr(input, '\n');
        if (!newline)
        {
          printf("Input string is too long and will be rejected\n");
          /**
           * Continue reading from stdin until we find the newline
           * character
           */
          while (!newline && fgets(input, sizeof input, stdin))
            newline = strchr(input, '\n');
        }
        else
        {
          *option = input[0];
          result = 1;
        }
      }
      else
        printf("Received error or EOF on read\n");
    
      return result;
    }
    

    是的,在一个愚蠢的菜单选项中阅读需要做很多工作,这就是简单的版本。欢迎来到 C 中交互式输入处理的奇妙世界。

    【讨论】:

      【解决方案3】:

      getchar() 返回输入缓冲区中的第一个字符,并将其从输入缓冲区中删除。但是其他字符仍在输入缓冲区中(在您的示例中为\n)。再次调用getchar()之前需要清除输入缓冲区:

      void clearInputBuffer() // works only if the input buffer is not empty
      {
          do 
          {
              c = getchar();
          } while (c != '\n' && c != EOF);
      }
      

      【讨论】:

        【解决方案4】:

        getchar() 之后添加getchar() :P

        【讨论】:

        • 我想它会起作用,但它是安静的麻醉剂。
        • 这在某些情况下会产生问题,用户会发现自己不得不按两次回车键。
        【解决方案5】:

        怎么样

        #include <stdio.h>
        
        /*! getline() reads one line from standard input and copies it to line array
         * (but no more than max chars).
         * It does not place the terminating \n in line array.
         * Returns line length, or 0 for empty line, or EOF for end-of-file.
         */
        int getline(char line[], int max)
        {
          int nch = 0;
          int c;
          max = max - 1;            /* leave room for '\0' */
        
          while ((c = getchar()) != EOF) {
            if (c == '\n')
              break;
        
            if (nch < max) {
              line[nch] = c;
              nch = nch + 1;
            }
          }
        
          if (c == EOF && nch == 0)
            return EOF;
        
          line[nch] = '\0';
          return nch;
        }
        

        Source

        【讨论】:

        • 我不能使用字符串或字符数组(这是一门课程的工作)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-21
        • 1970-01-01
        相关资源
        最近更新 更多