在 c 上使用 getchar() 会得到“Enter”;输入后

发布于 2024-09-28 07:33:39 字数 153 浏览 5 评论 0原文

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

我该如何解决这个问题?

I'm trying to write a simple program that asks a user to choose from a menu in a loop.
I use getchar() to get the input, however i've noticed that when I enter a char and press 'Enter' the program makes two loops (as if i pressed twice) one the char as an input and another for 'Enter' as an input.

How do I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

北陌 2024-10-05 07:33:40

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

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

getchar() returns the first character in the input buffer, and removes it from the input buffer. But other characters are still in the input buffer (\n in your example). You need to clear the input buffer before calling getchar() again:

void clearInputBuffer() // works only if the input buffer is not empty
{
    do 
    {
        c = getchar();
    } while (c != '\n' && c != EOF);
}
写给空气的情书 2024-10-05 07:33:40

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

Add a getchar() after the getchar() :P

紫竹語嫣☆ 2024-10-05 07:33:40

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

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

The easiest way is to filter out the enter key as the return value from getchar

char c = (char)getchar();
if ( c != '\n' ) {
  ...
}
檐上三寸雪 2024-10-05 07:33:40

怎么样

#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;
}

来源

How about

#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

落墨 2024-10-05 07:33:40

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

有几种选择。如果您的菜单选项是编号的,您可以使用 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 转换说明符读取该字符,并且将停留在输入流中,直到使用 %s%c 转换说明符调用 getchar()scanf()

更好的选择是使用 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 语言交互式输入处理的奇妙世界。

You've kind of answered your own question; you have to deal with the newline character somehow.

There are several options. If your menu options are numbered, you can use scanf() to read in an integer value and switch based on that:

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;
}

The advantage of this option is that the %d conversion specifier skips over any leading whitespace, including newline characters, so you don't have to worry about any unread \n clogging up the input stream (in fact, most of the conversion specifiers skip leading whitespace; %c doesn't, making it behave a lot like getchar()).

The disadvantage of this option is that if someone fat-fingers a non-digit character in their input, it won't be read with the %d conversion specifier, and will stay stuck in the input stream until a call to getchar() or scanf() with a %s or %c conversion specifier.

A better option is to read all input as character strings using fgets(), then parse and validate as necessary.

/**
 * 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;
}

Yes, that's a lot of work to read in one stupid menu option, and that's the simple version. Welcome to the wonderful world of interactive input processing in C.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文