Usando strtol para validar la entrada de enteros en ANSI C

Soy nuevo en progtwigción y en C en general y actualmente lo estudio en la universidad. Esto es para una tarea, así que me gustaría evitar las respuestas directas, pero hay más sugerencias o sugerencias en la dirección correcta.

Estoy tratando de usar strtol para validar mi entrada de teclado, más específicamente, probar si la entrada es numérica. He revisado otras preguntas aquí y en otros sitios y he seguido las instrucciones dadas a otros usuarios, pero no me han ayudado.

Por lo que he leído / entendido de strtol (long int strtol (const char * str, char ** endptr, int base);) si endptr no es un puntero nulo, la función establecerá el valor de endptr en el primer carácter despues del numero

Entonces, si ingresara 84948ldfk, el comando endptr apuntaría a ‘l’, diciéndome que hay caracteres distintos a los números en la entrada y que lo harían inválido.

Sin embargo, en mi caso, lo que está sucediendo es que no importa lo que ingrese, mi progtwig está devolviendo una entrada no válida. Aquí está mi código:

void run_perf_square(int *option_stats) { char input[MAX_NUM_INPUT + EXTRA_SPACES]; /*MAX_NUM_INPUT + EXTRA_SPACES are defined *in header file. MAX_NUM_INPUT = 7 *and EXTRA_SPACES *(for '\n' and '\0') = 2. */ char *ptr; unsigned num=0; /*num is unsigned as it was specified in the start up code for the *assignment. I am not allow to change it*/ printf("Perfect Square\n"); printf("--------------\n"); printf("Enter a positive integer (1 - 1000000):\n"); if(fgets(input, sizeof input, stdin) != NULL) { num=strtol(input, &ptr, 10); if( num > 1000001) { printf("Invalid Input! PLease enter a positive integer between 1 and 1000000\n"); read_rest_of_line(); /*clears buffer to avoid overflows*/ run_perf_square(option_stats); } else if (num <= 0) { printf("Invalid Input! PLease enter a positive integer between 1 and 1000000\n"); run_perf_square(option_stats); } else if(ptr != NULL) { printf("Invalid Input! PLease enter a positive integer between 1 and 1000000\n"); run_perf_square(option_stats); } else { perfect_squares(option_stats, num); } } } 

¿Alguien puede ayudarme en la dirección correcta? Obviamente, el error está en mi condición if (ptr! = NULL) , pero según tengo entendido, parece correcto. Como dije, he visto preguntas anteriores similares a esto y seguí el consejo de las respuestas, pero no parece funcionar para mí. Por lo tanto, pensé que era mejor pedir mi ayuda adaptada a mi propia situación.

¡Gracias por adelantado!

EDIT: Ok, lo tengo funcionando y después de algunas pruebas parece estar funcionando correctamente. Fue un problema con mis declaraciones if. El siguiente código me funciona hasta ahora:

 if((input[0] != '\n' && (*ptr == '\0' || *ptr == '\n')) && num  0) { perfect_squares(option_stats, num); } else { printf("Invalid Input! PLease enter a positive integer between 1 and 1000000\n"); if(num > 1000001) { read_rest_of_line(); } run_perf_square(option_stats); } 

Probablemente limpiaré el enunciado if para hacerlo un poco menos confuso, pero feliz con los resultados hasta ahora.

Está verificando el resultado de strtol en el orden incorrecto, verifique primero ptr , no verifique ptr contra NULL , desrénselo y verifique que apunte al terminador de cadena NUL ( '\0' ).

 if (*ptr == '\0') { // this means all characters were parsed and converted to `long` } else { // this means either no characters were parsed correctly in which // case the return value is completely invalid // or // there was a partial parsing of a number to `long` which is returned // and ptr points to the remaining string } 

num > 1000001 también necesita ser num > 1000000

num < 0 también debe ser num < 1

También puede reorganizar y realizar algunos ajustes lógicos para colapsar su secuencia de sentencias if hasta una única twig no válida y una twig aceptable.

OP quisiera evitar respuestas directas ….

validar entrada de enteros

  1. Separación de E / S de la validación – 2 funciones diferentes.

  2. E / S: Asume una entrada hostil. (Texto, demasiado texto, muy poco texto. Errores de E / S). ¿Desea consumir espacios iniciales como parte de E / S? ¿Desea consumir 0 inicial como parte de I / O? (sugiere no)

  3. Valide la cadena (¿NULL, espacio inicial correcto ?, dígitos después de un espacio final, demasiado corto, demasiado largo, bajo rango, sobre rango, Es 123.0 un entero correcto)

  4. strtol() es tu amigo para hacer el levantamiento de conversión pesado. Compruebe cómo errno debe configurarse y probarse después. Utilice el endptr . Si su valor se establece antes. Cómo probar después. Consume espacios iniciales, ¿está bien? Convierte el texto en un long , pero OP quiere el “entero” nebuloso.

Qapla ‘

La función strtol devuelve long int, que es un valor firmado. Le sugiero que use otra variable (entry_num), que podría probar para <0, detectando así números negativos.

También sugeriría que la expresión regular podría probar la entrada de cadena para los dígitos y la entrada válida, o podría usar strtok y cualquier cosa menos dígitos como delimitador 😉 O podría escanear la cadena de entrada utilizando la validación, algo como:

 int validate_input ( char* input ) { char *p = input; if( !input ) return 0; for( p=input; *p && (isdigit(*p) || iswhite(*p)); ++p ) { } if( *p ) return 0; return 1; }