How to check if user input is a float number in C?
Solution 1:
Have you read any documentation on scanf(3)
?
You need to check the return value like this
double value;
if (scanf("%lf", &value) == 1)
printf("It's float: %f\n", value);
else
printf("It's NOT float ... \n");
There is a way I prefer because it gives more control on subsequent input, scanf()
is rarely really useful. Instead try fgets()
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char buffer[100];
double value;
char *endptr;
if (fgets(buffer, sizeof(buffer) stdin) == NULL)
return -1; /* Unexpected error */
value = strtod(buffer, &endptr);
if ((*endptr == '\0') || (isspace(*endptr) != 0))
printf("It's float: %f\n", value);
else
printf("It's NOT float ...\n");
}
Solution 2:
The best way to test if a string converts to a double
is to use strtod()
.
strtod()
can be tricky to use. With strtod(char *s, char *endptr)
, if s == endptr
, conversion failed. Else check the string starting at endptr
for offending characters.
Overflow/underflow issues are not addressed here other than to say strtod()
and conversion to float
will readily convert to zero or infinity - both which are typically representable as a float
.
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
bool is_float(const char *s, float *dest) {
if (s == NULL) {
return false;
}
char *endptr;
*dest = (float) strtod(s, &endptr);
if (s == endptr) {
return false; // no conversion;
}
// Look at trailing text
while (isspace((unsigned char ) *endptr))
endptr++;
return *endptr == '\0';
}
void is_float_test(const char *s) {
float x;
printf("Test(\"%s\"):\n", s ? s : "NULL");
if (is_float(s, &x)) {
printf("Good (float) %e\n", x);
} else {
puts("Bad (float)");
}
}
int main(void) {
// Test cases
is_float_test("123");
is_float_test(" 123");
is_float_test("123.456\n");
is_float_test("123 ");
is_float_test("123e123");
is_float_test("123e456");
is_float_test(" 123 xyz");
is_float_test(" abc");
is_float_test(" ");
is_float_test("");
// Chance for user input
char buffer[80];
is_float_test(fgets(buffer, sizeof buffer, stdin));
return 0;
}
Output
Test("123"):
Good (float) 1.230000e+02
Test(" 123"):
Good (float) 1.230000e+02
Test("123.456
"):
Good (float) 1.234560e+02
Test("123 "):
Good (float) 1.230000e+02
Test("123e123"):
Good (float) inf
Test("123e456"):
Good (float) inf
Test(" 123 xyz"):
Bad (float)
Test(" abc"):
Bad (float)
Test(" "):
Bad (float)
Test(""):
Bad (float)