C: Múltiples escaneos, cuando ingreso un valor para un escaneo, se salta el segundo escaneo [duplicate]

5 minutos de lectura

avatar de usuario
Nieve_Mac

Tengo este bloque de código (las funciones se omiten porque la lógica es parte de una tarea):

#include <stdio.h>

int main()
{
    char c="q";
    int size; 

    printf("\nShape (l/s/t):");
    scanf("%c",&c);

    printf("Length:"); 
    scanf("%d",&size);

    while(c!='q')
    {
        switch(c)
        {
            case 'l': line(size); break; 
            case 's': square(size); break;
            case 't': triangle(size); break; 
        }


        printf("\nShape (l/s/t):");
        scanf("%c",&c);

        printf("\nLength:"); 
        scanf("%d",&size);
    }

    return 0; 
}

Los dos primeros Scanf funcionan muy bien, no hay problema una vez que entramos en el ciclo while, tengo un problema donde, cuando se supone que se le solicita que ingrese un nuevo carácter de forma, en su lugar salta al printf de longitud y espera a tomar la entrada desde allí para un carácter, luego un decimal en la siguiente iteración del ciclo.

iteración prebucle:

Scanf: Forma. Funciona genial
Scanf: Longitud. No hay problema

Bucle 1.

Scanf: Forma. Salta sobre esto
Scanf: longitud. Problema, este escaneo se asigna al carácter de forma.

Bucle 2
Scanf: Forma. Salta sobre esto
Scanf: longitud. Problema, este scanf se asigna al tamaño int ahora.

¿Por qué está haciendo esto?

avatar de usuario
Thomas Padrón-McCarthy

scanf("%c") lee el carácter de nueva línea del INGRESAR llave.

Cuando escribes digamos 15escribes un 1un 5 y luego presione el botón INGRESAR llave. Así que ahora hay tres caracteres en el búfer de entrada. scanf("%d") lee el 1 y el 5interpretándolos como el número 15, pero el carácter de nueva línea todavía está en el búfer de entrada. Él scanf("%c") leerá inmediatamente este carácter de nueva línea y el programa pasará al siguiente scanf("%d")y espere a que introduzca un número.

El consejo habitual es leer líneas completas de entrada con fgets, e interprete el contenido de cada línea en un paso separado. Una solución más simple a su problema inmediato es agregar un getchar() después de cada scanf("%d").

  • Él scanf("%d"); getchar(); la combinación falla si el usuario ingresa accidentalmente un espacio (u otra basura) después del número.

    – ilkkachu

    11 de junio de 2017 a las 10:14

El problema básico es que scanf() deja la nueva línea después del número en el búfer y luego la lee con %c en el próximo pase. En realidad, esta es una buena demostración de por qué no uso scanf(); Yo uso un lector de línea (fgets()por ejemplo) y sscanf(). Es más fácil de controlar.

Probablemente puedas rescatarlo usando " %c" en vez de "%c" para la cadena de formato. Las causas en blanco scanf() para omitir los espacios en blanco (incluidas las nuevas líneas) antes de leer el carácter.

Pero a la larga será más fácil rendirse. scanf() y fscanf() y use fgets() o equivalente más sscanf(). Aparte de todo lo demás, el informe de errores es mucho más fácil cuando se tiene toda la cadena con la que trabajar, no las gotas que dejan atrás. scanf() después de que falla.

También debe, siempre, comprobar que obtiene un valor convertido de scanf(). La entrada falla, de manera rutinaria y horrible. No permita que arruine su programa porque no lo comprobó.

avatar de usuario
jon z

Intente agregar un espacio en el scanf.

scanf(" %d", &var);
//     ^
//   there

Esto causará scanf() para descartar todos los espacios en blanco antes de hacer coincidir un número entero.

  • De acuerdo a sección 7.21.6.2p8, scanf haría normalmente descarte todos los espacios en blanco antes de hacer coincidir un número entero, de todos modos, lo que hace que el espacio en blanco en esta cadena de formato no tenga sentido: “Los caracteres de espacio en blanco de entrada (según lo especificado por la función isspace) se omiten, a menos que la especificación incluya un [, c, or n specifier.”

    – autistic

    Feb 21, 2017 at 2:14

  • This won’t fix the issue. %d already skips leading whitespace characters.

    – Spikatrix

    Feb 21, 2017 at 2:43

user avatar
noMAD

Use the function

void seek_to_next_line( void )
{
    int c;
    while( (c = fgetc( stdin )) != EOF && c != '\n' );
}

to clear out your input buffer.

user avatar
Gargi Srinivas

The '\n' character is still left on the input stream after the first call to scanf is completed, so the second call to scanf() reads it in. Use getchar().

user avatar
guga

When you type the shape and ENTER, the shape is consumed by the first scanf, but the ENTER is not! The second scanf expects a number so, the ENTER is skipped because is considered a white space, and the scanf waits for a valid input ( a number) that, again, is terminated by the ENTER. Well, the number is consumed, but the ENTER is not, so the first scanf inside the while uses it and your shape prompt is skipped… this process repeats. You have to add another %c in the scanfs to deal with the ENTER key. I hope this helps!

user avatar
Byeonggon Lee

You can also use
scanf("%c%*c", &c);
to read two characters and ignore the last one (in this case ‘\n’)

¿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