c scanf

¿Cómo escanear solo un entero?



scanf (7)

Quiero que el código se ejecute hasta que el usuario ingrese un valor entero.

El código funciona para matrices char y char.

He hecho lo siguiente:

#include<stdio.h> int main() { int n; printf("Please enter an integer: "); while(scanf("%d",&n) != 1) { printf("Please enter an integer: "); while(getchar() != ''/n''); } printf("You entered: %d/n",n); return 0; }

El problema es si el usuario ingresa un valor flotante scanf lo aceptará.

Please enter an integer: abcd Please enter an integer: a Please enter an integer: 5.9 You entered: 5

¿Cómo se puede evitar eso?


Sé cómo se puede hacer esto usando fgets y strtol , me gustaría saber cómo se puede hacer esto usando scanf() (si es posible).

Como dicen las otras respuestas, scanf no es realmente adecuado para esto, fgets y strtol son una alternativa (aunque fgets tiene el inconveniente de que es difícil detectar un byte 0 en la entrada e imposible saber qué se ha ingresado después de un 0 -byte, si lo hay).

En aras de la integridad (y suponiendo que la entrada válida es un número entero seguido de una nueva línea):

while(scanf("%d%1[/n]", &n, (char [2]){ 0 }) < 2)

Alternativamente, use %n antes y después de %*1[/n] con supresión de asignación. Sin embargo, tenga en cuenta (de la página de manual de Debian ):

Esto no es una conversión, aunque puede suprimirse con el carácter * asignación-supresión. El estándar C dice: "La ejecución de una directiva %n no incrementa el recuento de asignaciones devuelto al finalizar la ejecución", pero el Corrigendum parece contradecir esto. Probablemente es aconsejable no hacer suposiciones sobre el efecto de %n conversiones en el valor de retorno.


  1. Tomas scanf() .
  2. Lo tiras a la basura.
  3. Utiliza fgets() para obtener una línea completa.
  4. Utiliza strtol() para analizar la línea como un entero, comprobando si consumió toda la línea.

char *end; char buf[LINE_MAX]; do { if (!fgets(buf, sizeof buf, stdin)) break; // remove /n buf[strlen(buf) - 1] = 0; int n = strtol(buf, &end, 10); } while (end != buf + strlen(buf));


Intente usar el siguiente patrón en scanf . Leerá hasta el final de la línea:

scanf("%d/n", &n)

No necesitará getchar() dentro del bucle ya que scanf leerá toda la línea. Los flotantes no coincidirán con el patrón scanf y la solicitud le pedirá un número entero nuevamente.


Si está configurado para usar scanf , puede hacer algo como lo siguiente:

int val; char follow; int read = scanf( "%d%c", &val, &follow ); if ( read == 2 ) { if ( isspace( follow ) ) { // input is an integer followed by whitespace, accept } else { // input is an integer followed by non-whitespace, reject } } else if ( read == 1 ) { // input is an integer followed by EOF, accept } else { // input is not an integer, reject }


Una posible solución es pensarlo al revés: aceptar un flotante como entrada y rechazar la entrada si el flotante no es un entero:

int n; float f; printf("Please enter an integer: "); while(scanf("%f",&f)!=1 || (int)f != f) { ... } n = f;

Aunque esto permite al usuario ingresar algo como 12.0, o 12e0, etc.


Usa fgets y strtol ,

Un puntero al primer carácter que sigue a la representación entera en s se almacena en el objeto señalado por p , si *p es diferente de /n entonces tiene una entrada incorrecta.

#include <stdio.h> #include <stdlib.h> int main(void) { char *p, s[100]; long n; while (fgets(s, sizeof(s), stdin)) { n = strtol(s, &p, 10); if (p == s || *p != ''/n'') { printf("Please enter an integer: "); } else break; } printf("You entered: %ld/n", n); return 0; }


Usar fgets() es mejor.

Para resolver solo usando scanf() para la entrada, busque un int y el siguiente char .

int ReadUntilEOL(void) { char ch; int count; while ((count = scanf("%c", &ch)) == 1 && ch != ''/n'') ; // Consume char until /n or EOF or IO error return count; } #include<stdio.h> int main(void) { int n; for (;;) { printf("Please enter an integer: "); char NextChar = ''/n''; int count = scanf("%d%c", &n, &NextChar); if (count >= 1 && NextChar == ''/n'') break; if (ReadUntilEOL() == EOF) return 1; // No valid input ever found } printf("You entered: %d/n", n); return 0; }

Este enfoque no vuelve a solicitar si el usuario solo ingresa espacios en blanco, como solo Enter .