Duda sobre scanf

Iniciado por UsuarioZ, 16 Noviembre 2019, 02:12 AM

0 Miembros y 1 Visitante están viendo este tema.

UsuarioZ

Si pido un entero (lo especifico como %d) e ingreso una letra o algo que no sea un entero empieza como una recursion infinita.

¿Como puedo evitar esto en C?

K-YreX

Si no estás seguro del tipo de dato que va a introducir el usuario por teclado deberías usar la función <fgets()> y almacenar la entrada en un <char[]> para después validarlo tú internamente.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

ThunderCls

Para entender cual es el problema primero debes entender como funciona scanf. Esta funcion trabaja con un buffer de entrada o lo que es lo mismo un espacio en memoria de donde obtendra su contenido. Dicho buffer puede provenir de teclado, fichero, pipe, etc (stdin). Luego la funcion scanf intenta leer el buffer segun le especificas en el formato y una vez lee satisfactoriamente, el contenido del buffer leido es consumido. El problema viene cuando scanf no es capaz de leer el buffer como le haz indicado, entonces la funcion falla y el contenido del buffer se queda intacto. En tu caso le dices a scanf que debe leer un entero "%d" pero esta falla al encontrarse con un caracter, por lo que la funcion regresa sin haber modificado el buffer de entrada. Ahora ese caracter estara en ese buffer hasta que "alguien" lo elimine o se limpie el buffer por completo, lo que hace que tu scanf se siga llamando indefinidamente.
Luego de esta teoria, la solucion al problema se reduce a simplemente asegurarte que el buffer es limpiado si tu scanf falla para evitar un loop infinito. Una posible solucion seria:

#define ENTER '\n'
#define CORRECT_INPUT_FLAG 2
char ret = '\0';
int number = 0;

if(scanf("%d%c", &number, &ret) != CORRECT_INPUT_FLAG || ret != ENTER)
{
    printf("Entrada invalida\n");
    while (getchar() != ENTER) { } // limpia el buffer de caracteres invalidos
}


Por otra parte scanf es inseguro, impredecible y dificil de manejar, una mejor solucion seria usar fgets()/getline() y sscanf() si necesitas parsear el contenido a variables.
Saludos
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/