Reputation: 17008
I need to check the 2nd command line argument to see if it's a valid floating point number.
#include <stdio.h>
#include <math.h>
long int fact(int n)
{
if (n >= 1)
return n*fact(n - 1);
else
return 1;
}
double func(int x0, int n)
{
int p = 2 * n + 1;
return (double)pow(x0, p) / (double)fact(p);
}
double sinh_(int x0, int N)
{
double sum = 0;
int i = 0;
for (i = 0; i <= N; i++)
{
sum = sum + func(x0, i);
}
return sum;
}
double err(int x0, int N)
{
return abs(sinh(x0) - sinh_(x0, N));
}
int main(int argc, char**argv)
{
double x0 = 0;
int N = 0;
printf("No of args %d\n", argc);
//if CLA doesn't have exactly 4 arguments passed return -1
//1st argument is app-name
//2nd argument is x0
//4th argument is N
if (argc >= 3)
{
printf("Err: no of arguments should be 2");
return -1;
}
//if the 2nd CLA is not a number, return -1
if (!isdigit(atof(argv[1])))
{
printf("1st argument must be a real value");
return -1;
}
//if the 3rd CLA is not a number, return -1
if (!isdigit(atoi(argv[2])))
{
printf("2nd argument must be an int value");
return -1;
}
x0 = atof(argv[1]);
N = atoi(argv[2]);
printf("Builtin sinh = %f", sinh(x0));
printf("Approx sinh = %f", sinh_(x0, N));
printf("Err value = %f", err(x0, N));
}
Upvotes: 1
Views: 121
Reputation: 13836
atof
does not return a status to indicate if the conversion was successful or not, you will need to use strtod
for that. Check if endptr
is NULL
after it returns, also check for any overflow or underflow.
double strtod(const char *nptr, char **endptr);
char *end = NULL;
double x0 = strtod(argv[1], &end);
if (*end) {
// error, not a valid floating point number
}
if (errno == ERANGE) {
// error, overflow or underflow
}
Upvotes: 2
Reputation: 17503
The strto...
family of functions such as strtod
to convert a string to a double
and strtol
to convert a string to a long int
can give you information about whereabouts in the string the conversion ended.
If the string does not start with optional whitespace followed by a valid number, they will report the conversion ended at the beginning of the string. Otherwise they will report the position of the character that caused the conversion to end. So to check for error, check the position has "moved on" from the beginning of the string, and check the characters at the reported end position.
The functions also check for out-of-range values, setting errno
to ERANGE
and returning specific values.
The code below checks that the string ends with a null terminator after the number, but in some circumstances, for a string containing multiple separated values, you might want to check for a valid separation character.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv)
{
double x0;
long int N;
char *endptr;
if (argc != 3)
{
fprintf(stderr, "usage: %s x0 N\n", argv[0]);
return 2;
}
errno = 0;
x0 = strtod(argv[1], &endptr);
if (endptr == argv[1] || *endptr != '\0')
{
fprintf(stderr, "1st argument must be a real value\n");
return 2;
}
if (errno == ERANGE)
{
fprintf(stderr, "1st argument out of range\n");
return 2;
}
errno = 0;
N = strtol(argv[2], &endptr, 10);
if (endptr == argv[2] || *endptr != '\0')
{
fprintf(stderr, "2nd argument must be an integer value\n");
return 2;
}
if (errno == ERANGE)
{
fprintf(stderr, "2nd argument out of range\n");
return 2;
}
printf("x0:%g; N:%ld\n", x0, N);
return 0;
}
I changed the type of N
to long int
for convenience because there isn't a strtoi
function that returns an int
.
Upvotes: 1