to check input is numeric(float)
1) Take input as a string char buf[Big_Enough]
. I'd expect 160 digits will handle all but the most arcane "float" strings1.
#define N 160
char buf[N];
if (fgets, buf, sizeof buf, stdin) {
2) Apply float strtof()
for float
, (strtod()
for double
, strtold()
for long double
).
char *endptr;
errno = 0;
float d = strtof(buf, &endptr);
// endptr now points to the end of the conversion, if any.
3) Check results.
if (buf == endptr) return "No_Conversion";
// Recommend to tolerate trailing white-space.
// as leading white-spaces are already allowed by `strtof()`
while (isspace((unsigned char)*endptr) {
endptr++;
}
if (*endptr) return "TrailingJunkFound";
return "Success";
4) Tests for extremes, if desired.
At this point, the input is numeric. The question remains if the "finite string" an be well represented by a finite float
: if a the |result| is in range of 0
or [FLT_TRUE_MIN...FLT_MAX]
.
This involves looking at errno
.
The conversion "succeed" yet finite string values outside the float
range become HUGE_VALF
which may be infinity or FLT_MAX
.
Wee |values| close to 0.0, but not 0.0 become something in the range [0.0 ... INT_MIN]
.
Since the goal is to detect is a conversion succeeded (it did), I'll leave these details for a question that wants to get into the gory bits of what value.
An alternative is to use fscanf()
to directly read and convert, yet the error handling there has its troubles too and hard to portably control.
1 Typical float
range is +/- 1038. So allowing for 40 or so characters makes sense. An exact print of FLT_TRUE_MIN
can take ~150 characters. To distinguish a arbitrarily "float" string from FLT_TRUE_MIN
from the next larger one needs about that many digits.
If "float" strings are not arbitrary, but only come from the output of a printed float
, then far few digits are needed - about 40.
Of course it is wise to allow for extra leading/trailing spaces and zeros.