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)
scanf()will not overflow.getline()is not standard C although source code readily available. Agreescanf()source be retired.