Reputation: 1414
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
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
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
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
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
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
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