Compruebe si la entrada es flotante o deténgase

scanf("%f", &num); 

Tengo que comprobar si es una variable flotante válida y dejar de ejecutar si tiene símbolos como @ o ! o % etc.

Sugerencias?

scanf no es tu amigo, aquí. Incluso si verifica el resultado para asegurarse de leer un argumento completo con éxito, eso no garantiza que la entrada sea válida en un sentido significativo.

Ingreso dado como:

 1!!!1!oneone! 

El %f parsing se detendrá (pero tendrá éxito) después de leer el primer 1 , y dejará el puntero de lectura en la siguiente ! . Esto puede no ser lo que usted considera “entrada válida”.

En ese caso, intente:

 if (scanf("%f%c", &f, &c) == 2 && isspace(c)) /* success */ 

Esto, sin embargo, aceptará cosas como:

 1 oneoneonespace!bang 

Si algo en la misma línea se considera basura, entonces se vuelve difícil, porque scanf no distingue entre espacios y nuevas líneas. Tal vez intente algo como esto:

 char buffer[1024]; if (fgets(buffer, sizeof(buffer), stdin) != NULL) { if (sscanf(buffer, "%f %c", &f, &c) == 1) /* success */ } 

Compruebe el valor de retorno de scanf() . Devolverá el número de entradas escaneadas con éxito, en su caso, debería ser 1 . Si no es igual a uno, podría ser -1, que significa “fin de archivo” o 0, lo que significa que “la entrada no era válida”.

El uso del especificador% f en scanf no escaneará nada más, si no se especifica ningún valor flotante, no se leerá nada. Debe comprobar el valor de retorno de scanf.

Hay unos pocos valores de retorno definidos:

 EOF = -1 invalid input = 0 valid = >0 

No puede verificar ambas condiciones en scanf . Yo sugeriría leer toda la entrada en una cadena, buscar caracteres especiales. Una vez que pase esta prueba, intente volver a procesarla en una cadena a través de sscanf . Para buscar caracteres especiales hay un strpbrk definido en string.h

 char* specials = "%@!"; char* buffer[SOME_SIZE]; double value; int err; scanf("%s", buffer); if( strpbrk(buffer, specials) ) return SPECIAL_FOUND; err = sscanf(buffer, "%f", &value); if(err <= 0) return NOT_VALID_INPUT; //NOTE: there should probably be not EOF case // process your value 

Nota: no revisé el código, es una idea aproximada para jugar.

Puede verificar el valor de retorno desde scanf() . Si miras esta página :

Valor de retorno

En caso de éxito, la función devuelve el número de elementos de la lista de argumentos completados correctamente. Este recuento puede coincidir con el número esperado de elementos o ser menor (incluso cero) debido a un error de coincidencia, un error de lectura o el scope del final del archivo .

Así que algo como:

 if ( scanf( "%f", &num ) <= 0 ) { // Stop the execution } // Continue 

Haré lo que quieras.

Lea su entrada como texto, luego conviértala con la función de biblioteca strtod ; que le permite verificar si la entrada contiene caracteres no válidos:

 #include  #include  #include  ... char buf=[81]; double result = 0.0; ... if ( fgets( buf, sizeof buf, stdin ) != NULL ) { char *chk; double tmp = strtod( buf, &chk ); if ( isspace( *chk ) || *chk == 0 ) result = tmp; else fprintf( stderr, "%s is not a valid floating-point number\n", buf ); } 

Después de la llamada a strtod , la variable chk apuntará al primer carácter de la cadena que no es parte de una constante de punto flotante válida. Si este carácter es un espacio en blanco o 0, entonces eres bueno; De lo contrario tienes mala entrada.

La ventaja de este método sobre scanf es que si su entrada comienza con un solo carácter válido (como "1blkjhsdf" ), convertirá y asignará el "1" y devolverá un 1, lo que indica una conversión exitosa, aunque Probablemente quiera rechazar esa entrada. También consume toda la cadena de entrada (siempre que el búfer de entrada sea lo suficientemente grande), por lo que no deja basura en la secuencia de entrada para entorpecer la próxima lectura.

scanf es una buena herramienta para usar cuando sabe que su entrada está bien formada; De lo contrario, mejor utilizar el método anterior.