El uso de getchar () en c obtiene el ‘Enter’ después de la entrada [duplicate]

4 minutos de lectura

El uso de getchar en c obtiene el Enter
Boca de dragón

Estoy tratando de escribir un programa simple que le pida al usuario que elija de un menú en un bucle. Uso getchar () para obtener la entrada, sin embargo, noté que cuando ingreso un carácter y presiono ‘Enter’, el programa hace dos bucles (como si presionara dos veces) uno el char como entrada y otro para ‘Enter’ como entrada.

¿Cómo puedo solucionar esto?

getchar() devuelve el primer carácter en el búfer de entrada y lo elimina del búfer de entrada. Pero otros caracteres todavía están en el búfer de entrada (\n en tu ejemplo). Debe borrar el búfer de entrada antes de llamar getchar() otra vez:

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

El uso de getchar en c obtiene el Enter
jaredpar

La forma más sencilla es filtrar la tecla Intro como el valor de retorno de getchar

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

  • Supongo que quisiste decir getchar()? si es así, getchar() devuelve int.

    – Nyan

    19 de octubre de 2010 a las 15:41

  • @Nyan, getchar de hecho regresa int pero es legal asignar a char a través de conversiones. Referencia cplusplus.com/reference/clibrary/cstdio/getchar

    – JaredPar

    19/10/2010 a las 15:51

  • @Jared: sí, pero char está limitado a (normalmente) 256 valores, y necesita (normalmente) 257 valores para identificar TODOS caracteres Y FEO. Es por eso getchar() devuelve un int

    – pmg

    19 de octubre de 2010 a las 15:54

  • @pmg, soy consciente de eso. Simplemente estoy demostrando lo que solicitó el OP (cómo verificar la nueva línea).

    – JaredPar

    19 de octubre de 2010 a las 15:59

  • Ok, pero puedes demostrar con int c también 🙂

    – pmg

    19 de octubre de 2010 a las 17:13

Agrega un getchar() después de la getchar() :PAGS

  • Supongo que funcionaría, pero es un anestésico silencioso.

    – Snapdragon

    20 de octubre de 2010 a las 18:02

  • Eso producirá problemas en algunos casos en los que el usuario tendrá que presionar regresar dos veces.

    – Kaitán

    5 mayo 2017 a las 0:00

Qué tal si

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

Fuente

Has respondido a tu propia pregunta; tienes que lidiar con el carácter de nueva línea de alguna manera.

Hay varias opciones. Si sus opciones de menú son numeradopuedes usar scanf() para leer en un valor entero y cambiar basado en eso:

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

La ventaja de esta opción es que el %d El especificador de conversión omite cualquier espacio en blanco inicial, incluidos los caracteres de nueva línea, por lo que no tiene que preocuparse por ningún espacio sin leer. \n obstruyendo el flujo de entrada (de hecho, la mayoría de los especificadores de conversión omiten los espacios en blanco iniciales; %c no lo hace, haciendo que se comporte mucho como getchar()).

La desventaja de esta opción es que si alguien toca un carácter que no es un dígito en su entrada, no se leerá con el %d especificador de conversión, y permanecerá atascado en el flujo de entrada hasta que una llamada a getchar() o scanf() con un %s o %c especificador de conversión.

Una mejor opción es leer todas las entradas como caracteres. instrumentos de cuerda utilizando fgets()luego analice y valide según sea necesario.

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

Sí, eso es mucho trabajo para leer en una estúpida opción de menú, y esa es la versión simple. Bienvenido al maravilloso mundo del procesamiento de entrada interactivo en C.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad