leer - scanf char
Entrada de anĂ¡lisis con scanf en C (6)
Tal vez usar un ciclo while, no un do ... while loop ayudará. De esta forma, la condición se prueba antes de la ejecución del código. Prueba el siguiente fragmento de código:
while(command != ''q'')
{
//statements
}
Además, si conoce la longitud de la cadena con anticipación, es más fácil trabajar con bucles ''for'' que con bucles ''while''. También hay algunas formas más difíciles de determinar dinámicamente la longitud también.
Como una diatriba final: scanf()
no "chupa". Hace lo que hace y eso es todo. fgets()
es muy peligroso (aunque conveniente para aplicaciones sin riesgo), ya que no realiza ninguna comprobación de la entrada de forma nativa. Es MUY comúnmente conocido como un punto de explotación, específicamente ataques de desbordamiento de búfer, sobreescribiendo espacio en registros no asignados para esa variable. Por lo tanto, si elige usarlo, dedique un tiempo a realizar una comprobación / corrección de errores sólida.
Espero que esto ayude a alguien en el futuro, ¡ya que supongo que ya lo has manejado! ;)
He estado teniendo muchos problemas tratando de descubrir cómo usar scanf()
. Parece que funciona bien con números enteros, ya que es bastante directo scanf("%d", &i)
.
Donde me encuentro con problemas es usando scanf()
en bucles tratando de leer la entrada. Por ejemplo:
do {
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
} while (command != ''q'');
Cuando ingreso una entrada estructurada de manera válida como
c P101
, parece que se repite el ciclo antes de avisarme. Esto parece suceder incluso con un solo:scanf("%c", &c)
en un ciclo while. Hará el ciclo dos veces antes de avisarme nuevamente. ¿Qué lo hace girar dos veces y cómo lo detengo?
Cuando ingreso menos cantidad de datos de entrada que programáticamente no tendrían otro carácter o número como
q
, presionar enter parece indicarme que ingrese más. ¿Cómo obtengoscanf()
para procesar las entradas de caracteres individuales y dobles?
¡Está realmente roto! Yo no lo sabía
#include <stdio.h>
int main(void)
{
int counter = 1;
char command, prefix;
int input;
do
{
printf("counter: %d: ", counter);
scanf("%c %c%d", &command, &prefix, &input);
printf("---%c %c%d---/n", command, prefix, input);
counter++;
} while (command != ''q'');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
g3---
La salida parece encajar con la respuesta de Robert.
Cuando ingresa " c P101
", el programa recibe " c P101/n
". La mayoría de los especificadores de conversión omiten espacios en blanco principales, incluidas líneas nuevas, pero %c
no. La primera vez en todo hasta que se lea " /n
", la segunda vez alrededor de "/ n" se lee en el command
, " c
" se lee en prefix
, y " P
" queda, que no es un número, por lo que la conversión falla y " P101/n
" queda en la transmisión. La próxima vez que " P
" se almacene en el comando, " 1
" se almacenará en el prefijo, y 1
(del " 01
" restante) se almacenará en la entrada con " /n
" todavía en la transmisión la próxima vez. Puede solucionar este problema colocando un espacio al principio de la cadena de formato que omitirá cualquier espacio en blanco inicial, incluidas las líneas nuevas.
Algo similar está sucediendo para el segundo caso, cuando ingresa " q
", " q/n
" se ingresa en la secuencia, la primera vez que se lee " q
", la segunda vez que se lee " /n
", solo en la tercera llamada es la segunda lectura " q
", puede evitar nuevamente el problema agregando un carácter de espacio al comienzo de la cadena de formato.
Una mejor forma de hacerlo sería usar algo como fgets () para procesar una línea a la vez y luego usar sscanf () para realizar el análisis sintáctico.
Una vez que tienes la cadena que contiene la línea. es decir, "C P101", puede usar las capacidades de análisis de sscanf.
Ver: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html
scanf apesta, por las razones que ya has descubierto. Es mucho mejor usar algo para obtener toda la línea y luego analizarla.
Para la pregunta 1, sospecho que tienes un problema con tu printf()
, ya que no hay una terminación "/ n".
El comportamiento predeterminado de printf
es almacenar el buffer hasta que tenga una línea completa. Eso es a menos que cambie explícitamente el almacenamiento en búfer en stdout
.
Para la pregunta 2, acaba de golpear uno de los mayores problemas con scanf()
. A menos que su entrada coincida exactamente con la cadena de exploración que ha especificado, sus resultados no serán los esperados.
Si tienes una opción, obtendrás mejores resultados (y menos problemas de seguridad) ignorando scanf()
y haciendo tu propio análisis sintáctico. Por ejemplo, use fgets()
para leer una línea completa en una cadena, y luego procese los campos individuales de la cadena - tal vez incluso usando sscanf()
.