You can do it using strtol()
and strtod()
and comparing the end pointers, e.g. this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buffer[100];
char * endptr_n;
char * endptr_d;
long n;
double d;
fgets(buffer, 100, stdin);
n = strtol(buffer, &endptr_n, 10);
if ( endptr_n == buffer ) {
fputs("You didn't enter a number.", stderr);
return EXIT_FAILURE;
}
d = strtod(buffer, &endptr_d);
if ( *endptr_d == '\0' || *endptr_d == '\n' ) {
if ( endptr_d == endptr_n ) {
puts("You entered just a plain integer.");
} else {
puts("You entered a floating point number - invalid.");
}
} else {
puts("You entered garbage after the number - invalid.");
}
return EXIT_SUCCESS;
}
outputs:
paul@local:~/src/c$ ./testint
2
You entered just a plain integer.
paul@local:~/src/c$ ./testint
2.3
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
3e4
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
4e-5
You entered a floating point number - invalid.
paul@local:~/src/c$ ./testint
423captainpicard
You entered garbage after the number - invalid.
paul@local:~/src/c$
It doesn't use scanf()
, but that's a good thing, and it avoids the need to manually check the input following the integer you read.
Obviously, if the only thing on the line is the number, then a lot of this becomes unnecessary, since you can just call strtol()
and check *endptr_n
immediately, but if there may be other stuff on the line this is how you can do it, e.g. if you want to accept an integer followed by anything non-numeric, but not a floating point followed by the same thing, you can just remove the if ( *endptr_d == '\0' || *endptr_d == '\n' )
logic.
EDIT: updated the code to show the check to *endptr
.