Cómo resolver definitivamente el problema de la corriente de entrada de scanf
Supongamos que quiero ejecutar el siguiente fragmento de código en C:
scanf("%d", &some_variable);
printf("algo algo\n\n");
printf("Presione [enter] para continuar...")
getchar(); //colocado para darle tiempo al usuario de leer el "algo algo"
¡Este fragmento no se pausará! El problema es que scanf
dejará el carácter “enter” (\n
) en el flujo de entrada1, arruinando todo lo que viene después; en este contexto, getchar()
se comerá el \n
y no esperará un nuevo carácter real.
Dado que me dijeron que no use fflush(stdin)
(realmente no entiendo por qué), la mejor solución que se me ocurrió es simplemente volver a definir la función scanf
al comienzo de mi código:
void nsis(int *puntero){ //nsis: siglas de "no shenanigans integer scanf"
scanf("%d", puntero);
getchar(); //esto limpiará el flujo de entrada cada vez que se llame a la función scan
}
Y luego simplemente usamos nsis
en lugar de scanf
. Esto debería funcionar. Sin embargo, parece una solución casera y parcheada, ¿cómo manejan este lío los desarrolladores profesionales de C? ¿No usan scanf
en absoluto? ¿Aceptan trabajar con un flujo de entrada sucio? ¿Cuál es el estándar en este caso?
No pude encontrar una respuesta definitiva en ninguna parte. Cada fuente que encontré mencionaba una solución diferente (y dudosa)…
EDITAR: En respuesta a todos los que comentan alguna versión de “simplemente no uses scanf”: está bien, puedo hacer eso, pero ¿cuál es el propósito de scanf
entonces? ¿Es simplemente una función inútil y rota que nunca se debería usar? ¿Por qué está en las bibliotecas en primer lugar?
Esto parece realmente absurdo, especialmente considerando que a todos los principiantes se les enseña a usar scanf
…
[1]: El \n
que queda es el que el usuario escribió al ingresar el valor de la variable some_variable
y no el presente en printf
.
davy.ai
La función
scanf
en C es una función ampliamente utilizada para tomar la entrada del usuario. Sin embargo, como se mencionó en la pregunta, puede dejar caracteres no deseados en el flujo de entrada, lo que puede causar problemas al intentar tomar la entrada nuevamente o leer desde el flujo de entrada. Hay algunas formas de solucionar este problema:fflush(stdin)
: Hay debates sobre si esta es una solución segura o no, ya que el comportamiento defflush(stdin)
no está definido en el estándar de C. Algunos compiladores pueden implementarlo mientras que otros no. Por lo tanto, es mejor evitar su uso.Usar
fgets
en lugar descanf
:fgets
permite leer la entrada como una cadena hasta una longitud especificada, y deja de leer al final de la línea, incluido el carácter de nueva línea. Por lo tanto, no deja caracteres no deseados en el flujo de entrada. Luego, la entrada se puede convertir al tipo de datos deseado utilizando funciones comostrtol
. Sin embargo, en comparación conscanf
,fgets
requiere más líneas de código y más verificación de errores.Escribir una función de entrada personalizada: Como se muestra en la pregunta, se puede crear una función de entrada personalizada que lea la entrada usando
scanf
y luego llame agetchar
para limpiar el flujo de entrada. Este enfoque es más conciso que usarfgets
, pero aún requiere verificación de errores y puede no ser adecuado para escenarios de entrada más complejos.En resumen, aunque
scanf
es una función útil para tomar entrada, tiene sus limitaciones y puede causar problemas con el flujo de entrada. Los desarrolladores profesionales de C pueden usar alternativas comofgets
o funciones de entrada personalizadas para manejar la entrada del usuario.