Yogeesh Seralathan
Yogeesh Seralathan

Reputation: 1414

Check if input is float else stop

scanf("%f", &num);

I have to check if thats a valid float variable and stop executing if it has symbols like @ or ! or % etc..

Suggestions?

Upvotes: 1

Views: 13572

Answers (6)

John Bode
John Bode

Reputation: 123468

Read your input as text, then convert it with the strtod library function; that allows you to check if the input contains any invalid characters:

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
...
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 );
}

After the call to strtod, the variable chk will point to the first character in the string that is not part of a valid floating-point constant. If this character is whitespace or 0, then you're good; otherwise you have bad input.

The advantage to this method over scanf is that if your input starts with just one valid character (such as "1blkjhsdf"), it will convert and assign the "1" and return a 1, indicating a successful conversion, even though you'd probably want to reject that input. It also consumes the entire input string (provided the input buffer is large enough), so it doesn't leave any garbage in the input stream to foul up the next read.

scanf is a good tool to use when you know your input is well-formed; otherwise, better to use the method above.

Upvotes: 1

sh1
sh1

Reputation: 4751

scanf is not your friend, here. Even if you check the result to ensure that you read one whole argument successfully, that doesn't really guarantee that the input is valid in a meaningful sense.

Given input like:

1!!!1!oneone!

the %f parsing will stop (but succeed) after reading the first 1, and leave the read pointer at the following !. This may not be what you consider "valid input".

In that case, try:

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

This will, however, accept things like:

1 oneoneonespace!bang

If anything on the same line is to be considered garbage, then it gets difficult, because scanf doesn't distinguish between spaces and newlines. Perhaps try something like this:

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

Upvotes: 3

Pierre Fourgeaud
Pierre Fourgeaud

Reputation: 14510

You can check the return value from scanf(). If you look at this page :

Return value

On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.

So something like :

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

will do what you want.

Upvotes: 0

luk32
luk32

Reputation: 16070

You cannot check for both of your conditions in scanf. I would suggest reading whole input into a string, look for special characters. Once this test passes, try re-processing it into a string via sscanf. To search for special characters there is a strpbrk defined in 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

Note: I did not check the code it's a rough idea to play with.

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129374

Check the return value from scanf(). It will return the number of successfully scanned inputs - in your case it should be 1. If it is not equal to one, it could be -1 which means "end of file" or 0, which means "input wasn't valid".

Upvotes: 3

phyrrus9
phyrrus9

Reputation: 1467

Using the %f specifier in scanf won't scan anything else, if no float is specified, nothing will be read. You should check the return value of scanf.

There are a few defined return values:

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

Upvotes: 2

Related Questions