Reputation: 147
As a suggested exercise from Stephen Kochan's "Programming in C" (3rd ed.) I want to add some functionality to the strToInt
function which turns a string into an integer. The function has a return type int
which is is fine, if the passed string literal is valid (like "123" or "13"). But if the string contains any non-numerical values (e.g. "12x3", "foo") an error message should be printed and and the function exited. Since the return type is int
, an integer needs to be returned, but in this case this might be misleading. So my question is, what should be returned in such a case so that the returned value / type is unambiguous about the fact, that an invalid string literal has been passed and cannot be confused with a valid return value?
int strToInt(const char string[])
{
int i = 0, intValue, result = 0;
// check whether string passed is a valid literal
while (string[i] != '\0')
{
if (string[i] < '0' || string[i] > '9')
{
printf("ValueError: Invalid literal\n");
return; // what should be returned here?
}
++i;
}
for (i = 0; string[i] >= '0' && string[i] <= '9'; ++i)
{
intValue = string[i] - '0';
result = result * 10 + intValue;
}
return result;
}
Upvotes: 4
Views: 1248
Reputation: 30926
Well do what strto*
functions do - they return the converted number (if any) and then resets the pointer to the beginning of the part that it can't make out. With this same tone it does many things - you can get a clear idea of it if you go through the standard.
So in case of the example given 12x3
your function may return 12
and then make the pointer point to the appropriate position in the string. This is providing the error information by the pointer passed and then returning as much as it could parse from the input.
In case of strtol
([long int strtol(const char *nptr, char **endptr, int base);]
)from man
page we can see that when endptr
is set to the end of the string then that means whole string i sparsed successfully. In case of partial conversion that endptr
will not point to middle of the string.
Same way imitating the strto*
function we can see that it sets the errno
to appropriate number to denote different problems ( ERANGE
etc) - so along with that you can set it to give user a precise error report.
Upvotes: 0
Reputation: 9062
This is an interesting question in software engineering and there is no "best answer" to it.
In some cases, assigning a specific value of a range might work. For example, in the standard C library, some character manipulation functions, such as getc
, have their return type set to int rather than char. This is to be able to return -1 as an error code.
Other functions, such as strtod
simply return 0 if there was no possible conversion from string to double (this can be argued whether is a good or not approach). If something wrong happens, they return a special value (still a valid double) and set errno
,
Errno seems to be the standard approach in the unix world to error reporting. At the core, it is basically a global variable that stores the error code of the last error. Most system calls return a specific value when something occurs, and then you are supposed to check the error code in errno to see what happened.
Upvotes: 2
Reputation: 170173
// what should be returned here?
Nothing you can return here that won't look like a valid result. The way this is commonly solved is by moving the result to an output parameter. Thus freeing the return value for a status that indicates the success of the operation. For instance:
#include <stdbool.h>
bool strToInt(const char string[], int* outInt) {
// check whether string passed is a valid literal
while (string[i] != '\0')
{
if (string[i] < '0' || string[i] > '9')
{
printf("ValueError: Invalid literal\n");
return false;
}
}
int result = 0;
for (int i = 0; string[i] >= '0' && string[i] <= '9'; ++i)
{
intValue = string[i] - '0';
result = result * 10 + intValue;
}
if (outInt) // Or you may move the check earlier and return false too
*outInt = result;
return true;
}
You may of course return any type and not just a bool. Many software systems return one of several integral values that may indicate any of several ways the operation can fail. So the error handling can be more exact and sophisticated.
Upvotes: 3