Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to indicate an error because all numbers are valid return values?

Tags:

c

  • Compiler: GCC 4.4.5 (Code::Blocks)
  • Platform: Linux Kernel Version 2.6.32-5-686 (Debian)

I am currently writing a function that converts character strings into double longs. I am aware that there is already a function that does this. I am simply writing this function for practice but I currently don't know what to do.

My function worked correctly when it could only handle positive double longs because I could return -1 if their was an invalid character in the string. But I want the function to be able to handle negative double longs as well as positive. I don't know what I am supposed to do in this situation because now all real numbers are valid return values. I thought about continuing the conversion even if invalid characters are present by either converting the invalid characters into their decimal values or simply ignoring the invalid characters and picking out only valid characters 0-9 (decimal 48-57). I also thought about returning a pointer to a double long and using a NULL address to indicate that an invalid character was found or maybe I could just set errno like the function readdir(). I am not sure how I would go about setting errno or if that is even allowed. So my question overall is what would you guys recommend I do in this situation? Also please note that I haven't included handling for negative double longs yet and the function will simply ignore invalid characters: for example $&3%7AJ89 will be converted to 3789.

double long cstrtodl(const char *cstr)
{
double long power;
double long dl = 0;
int decimal_place;
int bool_decimal = 0;

for(decimal_place = 1; cstr[decimal_place] != '\0'; decimal_place++)
{
    if(cstr[decimal_place] == '.')
    {
        bool_decimal = decimal_place;
        break;
    }
}

for(decimal_place--, power = 1; decimal_place >= 0; decimal_place--, power *= 10)
{
    printf("[%i] = %i(%c)\nPOWER = %LF\nINTEGER = %LF\n", decimal_place, (int)cstr[decimal_place], cstr[decimal_place], power, dl);
    switch(cstr[decimal_place])
    {
        case 48:
            dl += 0 * power;
        break;

        case 49:
            dl += 1 * power;
        break;

        case 50:
            dl += 2 * power;
        break;

        case 51:
            dl += 3 * power;
        break;

        case 52:
            dl += 4 * power;
        break;

        case 53:
            dl += 5 * power;
        break;

        case 54:
            dl += 6 * power;
        break;

        case 55:
            dl += 7 * power;
        break;

        case 56:
            dl += 8 * power;
        break;

        case 57:
            dl += 9 * power;
        break;

        default:
            power /= 10;
        break;
    }
}

if(bool_decimal > 0)
{
    for(decimal_place = bool_decimal+1, power = 10; cstr[decimal_place] != '\0'; decimal_place++, power *= 10)
    {
        printf("[%i] = %i(%c)\nPOWER = %LF\nINTEGER = %LF\n", decimal_place, (int)cstr[decimal_place], cstr[decimal_place], power, dl);
        switch(cstr[decimal_place])
        {
            case 48:
                dl += 0 / power;
            break;

            case 49:
                dl += 1 / power;
            break;

            case 50:
                dl += 2 / power;
            break;

            case 51:
                dl += 3 / power;
            break;

            case 52:
                dl += 4 / power;
            break;

            case 53:
                dl += 5 / power;
            break;

            case 54:
                dl += 6 / power;
            break;

            case 55:
                dl += 7 / power;
            break;

            case 56:
                dl += 8 / power;
            break;

            case 57:
                dl += 9 / power;
            break;

            default:
                power /= 10;
            break;
        }
    }
}

return dl;
}
like image 909
John Vulconshinz Avatar asked Dec 15 '22 11:12

John Vulconshinz


1 Answers

Returning a pointer is complicated and inefficient, because you'd have to malloc a buffer and then remember to free it. That's a lot of overhead for returning a simple, fixed-size value. Instead, you can return a status code and write the result to a pointer:

// returns zero on success, -1 on error
int cstrtodl(const char *cstr, long double *result);

For some purposes, it might also be useful to know how much of the string was consumed, if you don't necessarily read all of it. In that case, you can return a size_t or ssize_t, and either 0 (no input consumed) or -1 on error. The caller can then check whether anything unexpected follows the number in the input string.

Setting errno is perfectly allowed in C.

like image 133
Fred Foo Avatar answered Dec 28 '22 23:12

Fred Foo