Tengo el siguiente programa:
int main(int argc, char *argv[])
{
char ch1, ch2;
printf("Input the first character:"); // Line 1
scanf("%c", &ch1);
printf("Input the second character:"); // Line 2
ch2 = getchar();
printf("ch1=%c, ASCII code = %d\n", ch1, ch1);
printf("ch2=%c, ASCII code = %d\n", ch2, ch2);
system("PAUSE");
return 0;
}
Como ha explicado el autor del código anterior: El programa no funcionará correctamente porque en la Línea 1, cuando el usuario presione Enter, dejará en el búfer de entrada 2 el carácter: Enter key (ASCII code 13)
y \n (ASCII code 10)
. Por lo tanto, en la Línea 2, leerá el \n
y no esperará a que el usuario ingrese un carácter.
OK, tengo esto. Pero mi primera pregunta es: ¿Por qué el segundo getchar()
( ch2 = getchar();
) no lee el carácter Enter key (13)
, en lugar de \n
?
A continuación, el autor propuso 2 formas de resolver tales problemas:
utilizar
fflush()
escribe una función como esta:
void clear (void) { while ( getchar() != '\n' ); }
Este código funcionó realmente. ¿Pero no puedo explicarme cómo funciona? Porque en la declaración while, usamos getchar() != '\n'
, eso significa leer cualquier carácter excepto '\n'
? si es así, en el búfer de entrada aún permanece el '\n'
carácter?
getchar()
leerá y devolverá esos caracteres; un usuario no necesitará presionar Enter en otro momento. Por otra parte, mientras que termios podrían ser comunes en Linux , no es parte de la biblioteca estándar C .scanf(" %c", &char_var)
trabajar e ignorar la nueva línea simplemente agregando un espacio antes del especificador% c?Puedes hacerlo (también) de esta manera:
fseek(stdin,0,SEEK_END);
fuente
fseek
está disponible parastdin
?Una forma portátil de borrar hasta el final de una línea que ya ha intentado leer parcialmente es:
int c; while ( (c = getchar()) != '\n' && c != EOF ) { }
Esto lee y descarta caracteres hasta que obtiene lo
\n
que indica el final del archivo. También verificaEOF
en caso de que el flujo de entrada se cierre antes del final de la línea. El tipo dec
debe serint
(o mayor) para poder mantener el valorEOF
.No hay una forma portátil de averiguar si hay más líneas después de la línea actual (si no las hay,
getchar
se bloqueará la entrada).fuente
Las líneas:
int ch; while ((ch = getchar()) != '\n' && ch != EOF) ;
no lee solo los caracteres antes del salto de línea (
'\n'
). Lee todos los caracteres de la secuencia (y los descarta) hasta el siguiente salto de línea (o se encuentra EOF) incluido . Para que la prueba sea verdadera, primero debe leer el salto de línea; así que cuando el bucle se detiene, el salto de línea fue el último carácter leído, pero se ha leído.En cuanto a por qué lee un salto de línea en lugar de un retorno de carro, es porque el sistema ha traducido el retorno a un salto de línea. Cuando se presiona enter, eso indica el final de la línea ... pero la secuencia contiene un avance de línea en su lugar, ya que ese es el marcador normal de fin de línea para el sistema. Eso podría depender de la plataforma.
Además, el uso
fflush()
en un flujo de entrada no funciona en todas las plataformas; por ejemplo, generalmente no funciona en Linux.fuente
while ( getchar() != '\n' );
es un bucle infinito que deberíagetchar()
regresarEOF
debido al final del archivo.int ch; while ((ch = getchar()) != '\n' && ch != EOF);
se puede usarLo que quizás no se dé cuenta es que la comparación ocurre después de
getchar()
eliminar el carácter del búfer de entrada. Entonces, cuando llegas al'\n'
, se consume y luego sales del bucle.fuente
puedes probar
scanf("%c%*c", &ch1);
donde% * c acepta e ignora la nueva línea
un método más en lugar de fflush (stdin) que invoca un comportamiento indefinido que puede escribir
while((getchar())!='\n');
no olvides el punto y coma después del ciclo while
fuente
"%*c"
escanea cualquier carácter (y no lo guarda), ya sea una nueva línea o algo más. El código se basa en que el segundo carácter es una nueva línea. 2)while((getchar())!='\n');
es un bucle infinito que deberíagetchar()
regresarEOF
debido al final del archivo.Encuentro un problema al intentar implementar la solución.
while ((c = getchar()) != '\n' && c != EOF) { }
Publico un pequeño ajuste 'Código B' para cualquiera que tenga el mismo problema.
El problema fue que el programa me mantuvo capturando el carácter '\ n', independientemente del carácter de entrada, aquí está el código que me dio el problema.
Código A
int y; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ continue; } printf("\n%c\n", toupper(y));
y el ajuste fue 'capturar' el carácter (n-1) justo antes de que se evalúe el condicional en el ciclo while, aquí está el código:
Código B
int y, x; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ x = y; } printf("\n%c\n", toupper(x));
La posible explicación es que para que el bucle while se rompa, tiene que asignar el valor '\ n' a la variable y, por lo que será el último valor asignado.
Si me perdí algo con la explicación, el código A o el código B, por favor dígame, apenas soy nuevo en c.
espero que ayude a alguien
fuente
while
ciclo. Después del bucle, puede considerarstdin
que está limpio / despejado yy
mantendrá '\n
' oEOF
.EOF
se devuelve cuando no hay una nueva línea presente y el búfer está agotado (si la entrada desbordaba el búfer antes de[ENTER]
presionar). - Usas efectivamente elwhile((ch=getchar())!='\n'&&ch!=EOF);
para masticar todos y cada uno de los caracteres en elstdin
búfer de entrada.unsigned char a=0; if(kbhit()){ a=getch(); while(kbhit()) getch(); } cout<<hex<<(static_cast<unsigned int:->(a) & 0xFF)<<endl;
-o-
usar tal vez usar
_getch_nolock()
.. ???fuente
kbhit()
ygetch()
son funciones declaradas<conio.h>
y solo disponibles como estándar en Windows. Se pueden emular en máquinas similares a Unix, pero hacerlo requiere cierto cuidado.Otra solución aún no mencionada es usar: rebobinar (stdin);
fuente
Me sorprende que nadie haya mencionado esto:
scanf("%*[^\n]");
fuente
Corto, portátil y declarado en stdio.h
stdin = freopen(NULL,"r",stdin);
No se cuelga en un bucle infinito cuando no hay nada en stdin para limpiar como la siguiente línea bien conocida:
while ((c = getchar()) != '\n' && c != EOF) { }
Un poco caro, así que no lo use en un programa que necesite borrar repetidamente el búfer.
Robó a un compañero de trabajo :)
fuente
freopen
única razón por la que existe es que no se puede asignar de forma portátil astdin
. Es una macro.Prueba esto:
stdin->_IO_read_ptr = stdin->_IO_read_end;
fuente