C – tratando de leer un solo carácter desde stdin (y falla) w / scanf / getchar

como parte de una tarea, estoy tratando de leer un solo carácter de stdin y actuar de acuerdo con él:

char choice; while (1) { printf("please enter [y]es, [n]o or [m]aybe: "); scanf("%c", choice); fflush(stdin); // validate input if (choice == 'y' || choice == 'n' || choice == 'm') { break; } else { printf("Please enter only \'y\', \'n\' or \'m\'!\n"); } } // do something with the input if (choice == 'y') { printf("you selected yes!\n"); } 

por alguna razón, scanf captura tanto el char como el line-feed después, por lo tanto procede a hacer algo con la entrada y luego también imprime el “Por favor ingrese solo ‘y’, ‘n’ o ‘m’!” línea. Si ingreso varios caracteres en el stdin, se imprimirá esa línea para todos ellos, mientras también se realiza correctamente para el primer carácter. Así por ejemplo:

 $ ./run please enter [y]es, [n]o or [m]aybe: y you selected yes! Please enter only 'y', 'n' or 'm'! $ ./run please enter [y]es, [n]o or [m]aybe: yes you selected yes! Please enter only 'y', 'n' or 'm'! Please enter only 'y', 'n' or 'm'! Please enter only 'y', 'n' or 'm'! $ 

Lo mismo sucede si uso getchar. ¿Qué me estoy perdiendo? Gracias.

Necesita un espacio entre scanf(" y el %c para que funcione correctamente:

 scanf(" %c", &choice); 

¡Y también necesita usar & elección, no elección!

EDITAR: Mientras lo hace, es posible que desee ver en do while() para ese bucle (a menos que el profesor específicamente dijo que utilice un break ), do while funciona bien al validar la entrada del usuario!

Mejor aún, use fgetc (). scanf () siempre debe ser un último recurso.

fflush () no está definido por ISO para flujos de entrada. Se define en la biblioteca C runtime de Microsoft, pero no es portátil.

Si bien la solución “espacio antes de% c” puede funcionar cuando el usuario ingresa los datos esperados, fallará de muchas maneras; intente ingresar “ynyn” por ejemplo. La entrada de consola está orientada a lin; su mejor apuesta es asegurarse de descartar toda la línea así:

 scanf( "%c", choice ) ; while( choice != '\n' && getchar() != '\n' ) /* do nothing*/ ; 

En primer lugar, lo mantendré breve. Debido a que no hay suficientes puntos para enviar un comentario. Si podemos ver ese número de o / p es (uno + el no de charcter) Esto se debe a que presionamos enter luego de ingresar los caracteres ‘\ n ‘que es un carácter no imprimible también se agrega después de su cadena.

 $ ./run please enter [y]es, [n]o or [m]aybe: y you selected yes! Please enter only 'y', 'n' or 'm'! -----------> it is due to reading of the '\n' by scanf 

EDITADO Debido a la insuficiencia de puntos, podría publicar esto como un comentario. Esta es una solución de las respuestas anteriores