Pregunta

He estado teniendo muchos problemas al tratar de averiguar cómo usar scanf () . Parece funcionar bien con los enteros, siendo bastante sencillo el scanf ("% d " ;, & amp; i) .

Donde estoy teniendo problemas es usando scanf () en los bucles que intentan leer la entrada. Por ejemplo:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. Cuando entro en una entrada con una estructura válida como c P101 , parece que vuelve a aparecer un bucle antes de preguntarme. Esto parece suceder incluso con una sola:

    scanf("%c", &c) 
    

    en un bucle while. Hará el bucle dos veces antes de volver a preguntarme. ¿Qué es lo que lo hace dos veces y cómo lo detengo?

  2. Cuando ingreso menos cantidad de entrada que programáticamente no tendría otro carácter o número como q , presionar Intro me indica que ingrese más. ¿Cómo obtengo scanf () para procesar entradas de caracteres simples y dobles?

¿Fue útil?

Solución

Cuando ingresa " c P101 " el programa recibe " c P101 \ n " ;. La mayoría de los especificadores de conversión omiten los espacios en blanco iniciales, incluidas las nuevas líneas, pero % c no. La primera vez alrededor de todo hasta el " \ n " se lee, la segunda vez alrededor de la " \ n " se lee en command , " c " se lee en prefix , y " P " queda lo que no es un número, por lo que la conversión falla y " P101 \ n " se deja en la corriente. La próxima vez que " P " se almacena en el comando, " 1 " se almacena en el prefijo, y 1 (del " 01 ") restante se almacena en la entrada con el " \ n " Todavía en la corriente para la próxima vez. Puede solucionar este problema poniendo un espacio al principio de la cadena de formato que omitirá cualquier espacio en blanco inicial, incluidas las nuevas líneas.

Está sucediendo algo similar para el segundo caso, cuando ingresas " q " ;, " q \ n " se ingresa al flujo, la primera vez alrededor de " q " se lee, la segunda vez que " \ n " se lee, solo en la tercera llamada está el segundo " q " Lea, puede evitar el problema nuevamente agregando un carácter de espacio al principio de la cadena de formato.

Una mejor manera de hacer esto sería usar algo como fgets () para procesar una línea a la vez y luego usar sscanf () para hacer el análisis.

Otros consejos

¡Está realmente roto! No lo sabia

#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.

Una vez que tenga la cadena que contiene la línea. es decir, " C P101 " ;, puede utilizar las habilidades de análisis de sscanf.

Ver: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf. html

Para la pregunta 1, sospecho que tiene un problema con su printf () , ya que no hay una terminación " \ n " ;.

El comportamiento predeterminado de printf es amortiguar la salida hasta que tenga una línea completa. Eso es a menos que cambie explícitamente el almacenamiento en búfer en stdout .

En la pregunta 2, acabas de encontrar uno de los mayores problemas con scanf () . A menos que su entrada coincida exactamente con la cadena de escaneo que ha especificado, sus resultados no se parecerán a lo que espera.

Si tiene una opción, obtendrá mejores resultados (y menos problemas de seguridad) al ignorar scanf () y hacer su propio análisis. Por ejemplo, use fgets () para leer una línea completa en una cadena y luego procese los campos individuales de la cadena & # 8212; tal vez incluso usando sscanf () .

Quizás usar un bucle while, no un bucle do ... while ayudará. De esta manera se prueba la condición antes de la ejecución del código. Pruebe el siguiente fragmento de código:

 while(command != 'q')
    {
        //statements
    }

Además, si conoce la longitud de la cadena antes de tiempo, puede ser mucho más fácil trabajar con los bucles 'for' que con los bucles 'while'. También hay formas más complicadas de determinar dinámicamente la longitud.

Como último rant: scanf () no " chupa. " Hace lo que hace y eso es todo. fgets () es muy peligroso (aunque es conveniente para aplicaciones sin riesgo), ya que no realiza ninguna comprobación de la entrada de forma nativa. Es muy conocido comúnmente como un punto de explotación, específicamente ataques de desbordamiento de búfer, sobrescribiendo el espacio en registros no asignados para esa variable. Por lo tanto, si elige usarlo, dedique un poco de tiempo a poner un poco de comprobación / corrección de errores.

¡Espero que esto ayude a alguien en el futuro ya que asumo que ya lo has manejado! ;)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top