Reputation: 12064
I am using strtod( ) function to extract an environment variable as a string, and then changing it to double using strtod:
enter code here
char strEnv[32];
strncpy(strEnv, getenv("LT_LEAK_START"), 31);
// How to make sure before parsing that env LT_LEAK_START is indeed a number?
double d = strtod(strEnv, NULL);
Now i want to make sure that this number entered by user is a number and not a string or special character. How can i make sure of that?
A code snippet would be of great help.
Thanks in advance.
Upvotes: 7
Views: 18753
Reputation: 153557
OP's code has issues:
getenv()
may return NULL
Consider a null pointer test of the result.
Not certainly a string
char strEnv[32];
strncpy(strEnv, getenv("LT_LEAK_START"), 31);
// strEnv is not certainly a string as it may lack a null character.
strEnv[31] = 0; // Add
The end pointer of strtod()
is useful, yet deserves more testing
// Conversion problems not detected. See following.
double d = strtod(strEnv, NULL);
char *endptr;
errno = 0;
double d = strtod(strEnv, &endptr);
if (d == endptr) {
return Error_No_conversion; // Like "", "+", "-.", "abc"
}
// Tolerate trailing white-space as leading space is OK
while (isspace(((unsigned char *)endptr)[0])) {
endptr++;
}
if (*endptr) {
return Error_Junk_after_number; // Like "876 - 5309"
}
// Optional pedantic testing.
if (errno == ERANGE) {
if (fabs(d) > 1.0) {
// Usually this is OK to just continue;
// `d` will have the signed value of HUGE_VAL (DBL_MAX or infinity)
; // return Error_Number_too_large;
} else {
// Usually this is OK to just continue;
// `d` will have the signed value of DBL_MIN or 0.0 or some small value
; // return Error_Number_too_small;
}
} else if (errno) {
// Usually this is OK to just continue;
; return Error_Implementation_specific_error;
}
// Success, now use `d`.
So far, this answer does not fail ""
nor "123 456"
.
Upvotes: 0
Reputation: 37208
Surely you could do worse than just reading the man page for strtod() and acting upon that. E.g. on my Linux system it says:
RETURN VALUE These functions return the converted value, if any. If endptr is not NULL, a pointer to the character after the last character used in the conversion is stored in the location referenced by endptr. If no conversion is performed, zero is returned and the value of nptr is stored in the location referenced by endptr. If the correct value would cause overflow, plus or minus HUGE_VAL (HUGE_VALF, HUGE_VALL) is returned (according to the sign of the value), and ERANGE is stored in errno. If the correct value would cause underflow, zero is returned and ERANGE is stored in errno.
That pretty much tells you what you need to do in order to handle errors. Also, like Johann Gerell said, you also need to check whether getenv() succeeded; a similar approach works there, i.e. check the man page and write error handling code according to that.
Upvotes: 3
Reputation: 108938
The 2nd argument to the strtod
function is useful.
char *err;
d = strtod(userinput, &err);
if (*err == 0) { /* very probably ok */ }
if (!isspace((unsigned char)*err)) { /* error */ }
Edit: examples added
The strtod
function tries to convert the initial portion of the 1st argument to a double and stops either when there are no more chars, or there is a char that can't be used to make a double.
input result ---------- ---------------------------- "42foo" will return 42 and leave err pointing to the "foo" (*err == 'f') " 4.5" will return 4.5 and leave err pointing to the empty string (*err == 0) "42 " will return 42 and leave `err` pointing to the spaces (*err == ' ')
Upvotes: 18
Reputation: 25581
getenv
- if it's NULL, then that environment variable doesn't exist.getenv
isn't NULL, then you have the value, as a string.char ** endptr
parameter of strtod
to NULL, but use it to check the validity of the converted value, also check for 0.0
.Upvotes: 1
Reputation: 10917
man strtod
: If no conversion is performed, zero is returned and the value of nptr is stored in the location referenced by endptr.
char * endptr;
double d = strtod(strEnv, &endptr);
if (strEnv == endptr)
/* invalid number */
else
...
Upvotes: 3
Reputation: 1101
I don't know much about this language but I do know that strtod() will return 0.0 if the input is wrong. Maybe you could use a regular expression to validate the input string is a number.
Upvotes: 0
Reputation: 19981
That second argument to strtod
, which you've set to NULL
, can be a pointer-to-pointer-to-char; the pointer-to-char that it points to will get set to the character after the last thing strtod
managed to parse. If that's the end of the string, or at least there's nothing after it but whitespace, then what you had was a number. Otherwise, it was something else.
Upvotes: 0