2010-03-02 12 views
9

Soy bastante nuevo en C y tengo un problema al ingresar datos en el programa.Entrada en C. Scanf before gets. Problema

Mi código:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) { 
    int a; 
    char b[20]; 

    printf("Input your ID: "); 
    scanf("%d", &a); 

    printf("Input your name: "); 
    gets(b); 

    printf("---------"); 

    printf("Name: %s", b); 

    system("pause"); 
    return 0; 
} 

Permite ID de entrada, pero sólo se salta el resto de la entrada. Si cambio el orden como este:

printf("Input your name: "); 
    gets(b); 

    printf("Input your ID: "); 
    scanf("%d", &a); 

Funcionará. Aunque, NO PUEDO cambiar el orden y lo necesito tal como está. Alguien me puede ayudar ? Tal vez necesito usar algunas otras funciones. ¡Gracias!

+1

obtiene (3): "El gets() función no se puede utilizar de forma segura Debido a su falta de comprobación de límites, y la incapacidad para el programa que llama a. confiablemente determinar la longitud de la siguiente línea entrante, el uso de esta función permite a los usuarios malintencionados cambiar arbitrariamente la funcionalidad de un programa en ejecución a través de un ataque de desbordamiento de búfer. Se recomienda que se use la función fgets() en todo c ases. (Consulte la FSA). " No lo use. –

+3

Más brevemente: Si usa' gets', volando ocelos de ataque rabioso se rasgará los ojos. Así que no. –

+2

'scanf' es ** evil * * - http://c-faq.com/stdio/scanfprobs.html – jschmier

Respuesta

10

Probar:.

scanf("%d\n", &a); 

obtiene sólo lee el '\ n' que Scanf hojas en También, usted debe utilizar fgets no obtiene: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/ para evitar posibles desbordamientos de búfer.

Editar:

si lo anterior no funciona, pruebe:

... 
scanf("%d", &a); 
getc(stdin); 
... 
+0

Hm. He intentado con scanf ("% d \ n", &a); pero no parece estar funcionando. Después de ingresar la identificación, simplemente no veo el programa haciendo nada más. – Dmitri

+0

¡Guau! ¡Gracias! Eso funcionó sin problemas! Gracias por los consejos sobre fgets. ¡Seguramente lo usaré! ¡Gracias! – Dmitri

7

scanf no consume la nueva línea y por lo tanto es un enemigo natural de fgets. No los juntes sin un buen truco. Ambas opciones funcionará:

// Option 1 - eat the newline 
scanf("%d", &a); 
getchar(); // reads the newline character 

// Option 2 - use fgets, then scan what was read 
char tmp[50]; 
fgets(tmp, 50, stdin); 
sscanf(tmp, "%d", &a); 
// note that you might have read too many characters at this point and 
// must interprete them, too 
+0

¡Impresionante! ¡Muchas gracias! – Dmitri

+0

Además, usar 'scanf ("% d% * c ", & a)' debería funcionar. El término '% * c' hace que' scanf' lea en un carácter (la nueva línea) pero el asterisco hace que el valor sea descartado. Esto hará que 'scanf' coma la nueva línea sin requerir una llamada de función separada. – bta

+0

Presenta ambas opciones como si tuvieran el mismo nivel, pero 'scanf' es tan difícil de usar correctamente que es mucho mejor evitar usarlo por completo (consulte el enlace de preguntas frecuentes comp.lang.c). Simplemente vaya con la opción 2. – jamesdlin

1
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) { 
     int a; 
     char b[20]; 
     printf("Input your ID: "); 
     scanf("%d", &a); 
     getchar(); 
     printf("Input your name: "); 
     gets(b); 
     printf("---------"); 
     printf("Name: %s", b); 
     return 0; 
} 



Note: 
    If you use the scanf first and the fgets second, it will give problem only. It will not read the second character for the gets function. 

    If you press enter, after give the input for scanf, that enter character will be consider as a input f or fgets. 
2

scanf no consumirá \ n por lo que será tomada por el se que sigue el scanf. enjuague la corriente de entrada después de escanear de esta manera.

#include <stdlib.h> 
#include <string.h> 

int main(void) { 
    int a; 
    char b[20]; 

    printf("Input your ID: "); 
    scanf("%d", &a); 
    fflush(stdin); 
    printf("Input your name: "); 
    gets(b); 

    printf("---------"); 

    printf("Name: %s", b); 

    system("pause"); 
    return 0; 
} 
+2

Tanto fflush (stdin) como fflush (NULL), en algunas bibliotecas C, eliminarán stdout y stderr, ¡pero esto es completamente imposible de usar! –

0

debe hacerlo de esta manera.

fgetc(stdin); 
    scanf("%c",&c); 
    if(c!='y') 
    { 
     break; 
    } 
    fgetc(stdin); 

para leer la entrada de scanf después de leer todo.

0

sólo tiene que utilizar 2 gets() funciones

Cuando se desea utilizar gets() después de un scanf(), se asegura de que utiliza 2 de la gets() funciones y para el caso anterior escribe el código como:

int main(void) { 
    int a; 
    char b[20]; 

    printf("Input your ID: "); 
    scanf("%d", &a); 

//the change is here********************* 
    printf("Input your name: "); 
    gets(b); 
    gets(b); 
//the change is here********************* 

    printf("---------"); 

    printf("Name: %s", b); 

    system("pause"); 
    return 0; 
} 

Para la explicación ([email protected]);

+0

bienvenido a SO! Recuerde que el inglés no es el primer idioma de todos, así que intente publicar respuestas que sean correctas desde el punto de vista gramatical, en lugar de utilizar 'u' para 'usted', lo que no funcionará con Google Translate. –

0

scanf("%d", &a); no se puede leer la declaración, porque %d solo acepta números enteros decimales. Así que agrega un \n al comienzo de la siguiente scanf para ignorar la última \n dentro del búfer.

Luego, scanf("\n%s", b); ahora puede leer la cadena sin problema, pero scanf se detiene para leer cuando encuentra un espacio en blanco. Por lo tanto, cambie %s a %[^\n].Significa: "leer Everthing pero \n"

scanf("\n%[^\n]", b);

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) { 
    int a; 
    char b[20]; 

    printf("Input your ID: "); 
    scanf("%d", &a); 

    printf("Input your name: "); 
    scanf("\n%[^\n]", b); 
    //first \n says to ignore last 'return' 
    //%[^\n] read until find a 'return' 
    printf("---------\n"); 
    printf("Name: %s\n\n", b); 

    system("pause"); 
    return 0; 
} 
+1

Agregue una explicación del código. – coatless

+0

Explicación agregada @Coatless –

0

La función scanf elimina los espacios en blanco de forma automática antes de tratar de analizar las cosas que no sean caracteres. %c, %n, %[] son excepciones que no eliminan el espacio en blanco inicial.

gets está leyendo la nueva línea que dejó scanf anterior. Coger el salto de línea usando getchar();

scanf("%d", &a); 
getchar(); // catches the newline character omitted by scanf("%d") 
gets(b); 

https://wpollock.com/CPlus/PrintfRef.htm

Cuestiones relacionadas