Claro, el "desbordamiento de buffer" es un problema típico en la programación, y que por supuesto debemos evitar.
Para C (en C++ el tamaño del arreglo se ajusta automáticamente) una solución sería usar
fgets(char *s, int size, FILE *stream), que limita la cantidad de caracteres leídos a
size - 1 (se resta uno porque la última posición está reservada para el nulo de terminación). En
stream hemos de poner
stdin para que lea de la entrada estándar (hay unas consideraciones con
fgets() que explicaré al final)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int getInt(char *);
int isInt(char * s);
int main( ) {
int x;
char msg[] = "Intro numero: ";
printf("Numero es: %d\n", getInt(msg));
}
int getInt(char *msg) {
#define N 3
char s[N + 1];
int i;
char clean_return;
do {
printf("%s", msg);
fgets(s, N + 1, stdin);
/* reemplazar '\n' (si se encuentra) por '\0' */
i = -1;
clean_return = 1;
while ( s[++i] != '\0' )
if ( s[i] == '\n' ) {
s[i] = '\0';
clean_return = 0;
break;
}
/* si no se pasó '\n' al arreglo, limpiarlo del bufer de entrada */
if ( clean_return ) getchar();
} while( *s == '\0' || !isInt(s) );
return atoi(s);
}
int isInt(char * s) {
int i = -1;
while ( s[++i] != '\0' ) {
if( !isdigit(s[i]) )
return 0;
}
return 1;
}
El programa pide al usuario un cadena, que es evaluada como entero siempre y cuando todos sus caracteres sean numéricos. De lo contrario, pide de nuevo. Al final imprime lo que leyó, para verificar.
Como ya se explicó, si por ejemplo declaras un arreglo
char[] de N+1 caracteres, entonces
fgets() lee como mucho N caractares. Si el fin de línea se encuentra dentro de esos N caracteres (si la cadena tiene una longitud menor N) entonces el fin de linea '\n' es pasado al arreglo. De lo contrario, (si la longitud de la cadena es mayor o igual a N) el '\n' no se pasa al arreglo y queda "pendiente" en el flujo de entrada del teclado. Por eso es necesario eliminarlo con
getchar()Se podría hacer una modificación al
isInt() con el objeto de admitir un único carácter de signo '-' al inicio de la cadena, así permitir números negativos.
El código propuesto está en C, lo que implementa una solución más "básica" que C++. Creo que una simple operación de lectura de datos por teclado no exige invocar el complejo modelo de objetos de E/S de C++ ..... (bueno aunque de ahí en adelante no opino más, ello depende del gusto del programador)