0

Hello there, I've written a C++ function 'stod', which converts a C++ string to a double ...
You're free to use this code for EVERYTHING you want ...
There's only one thing which I'm not appreciating:
It's not allowed to sell this source code to anyone !

The usage is simple:

double dbl;
string test = "25.23";
dbl = stod(test); /* We convert the string to a real double */

If you pass a string which can't be turned into a number, the function's output is always '0' ...

As you maybe already have found out (is this grammatically correct?) the function's name is inspired by the C-function 'atoi' ...

Hope you find this code useful !!!

P.S.: Sorry if my English is bad, my native language is Dutch ...

double stod(const string &strInput)
{
    /* STOD: String to double  */
    /* Written by Mathias Van Malderen */

    double dbl_one = 0;
    double dbl_two = 0;
    double dbl_final = 0;
    int strlen;
    bool dec_pt = false;
    int nums_before_dec = 0;
    int nums_after_dec = 0;

    strlen = strInput.length();

    /* Check whether the string can be transformed into a number */
    if(strInput[0] == '0' && strInput[1] == '0')
    {
        // invalid number !
        return 0;
    }
    for(int i = 0; i < strlen; i++)
    {
        if(strInput[i] == '0' || strInput[i] == '1' || strInput[i] == '2' || strInput[i] == '3' || strInput[i] == '4' || strInput[i] == '5' || strInput[i] == '6' || strInput[i] == '7' || strInput[i] == '8' || strInput[i] == '9')
        {
            // valid number
        } else if(strInput[i] == '.'){
            if(dec_pt)
            {
                // there was already a decimal point counted
                // invalid number !
                return 0;
            } else {
                dec_pt = true; // increment by one
            }
        } else {
            // invalid number !
            return 0;
        }
    }

    /* Convert the number */

    // STEP 1: Calculate the amount of numbers before/after the decimal point (if there's one)
    if(dec_pt) // if there's a decimal point in the number
    {
        for(int i = 0; i < strlen; i++)
        {
            if(strInput[i+1] != '.')
            {
                nums_before_dec++;
            } else {
                nums_before_dec++;
                break;
            }
        }
		nums_after_dec = strlen-nums_before_dec;
		nums_after_dec -= 1;
    } else {
		// This piece of code was added later as a BUGFIX !
		// Now the STOD-function is working 100% perfect !!!
		nums_after_dec = 0;
		nums_before_dec = strlen;
    }

    

    // STEP 2: Convert the string to a real number
    for(int i = 0; i < nums_before_dec; i++)
    {
        switch(strInput[i])
        {
            case '0':
                dbl_one += 0 * apow(10, (nums_before_dec - i));
                break;
            case '1':
                dbl_one += 1 * apow(10, (nums_before_dec - i));
                break;
            case '2':
                dbl_one += 2 * apow(10, (nums_before_dec - i));
                break;
            case '3':
                dbl_one += 3 * apow(10, (nums_before_dec - i));
                break;
            case '4':
                dbl_one += 4 * apow(10, (nums_before_dec - i));
                break;
            case '5':
                dbl_one += 5 * apow(10, (nums_before_dec - i));
                break;
            case '6':
                dbl_one += 6 * apow(10, (nums_before_dec - i));
                break;
            case '7':
                dbl_one += 7 * apow(10, (nums_before_dec - i));
                break;
            case '8':
                dbl_one += 8 * apow(10, (nums_before_dec - i));
                break;
            case '9':
                dbl_one += 9 * apow(10, (nums_before_dec - i));
                break;
            default:
                // invalid number !
                return 0;
        }
    }

    dbl_one = dbl_one / 10; // little fix

    for(int i = 0; i < nums_after_dec; i++)
    {
        switch(strInput[i + nums_before_dec + 1])
        {
            case '0':
                dbl_two += (0 / apow(10, i+1));
                break;
            case '1':
                dbl_two += (1 / apow(10, i+1));
                break;
            case '2':
                dbl_two += (2 / apow(10, i+1));
                break;
            case '3':
                dbl_two += (3 / apow(10, i+1));
                break;
            case '4':
                dbl_two += (4 / apow(10, i+1));
                break;
            case '5':
                dbl_two += (5 / apow(10, i+1));
                break;
            case '6':
                dbl_two += (6 / apow(10, i+1));
                break;
            case '7':
                dbl_two += (7 / apow(10, i+1));
                break;
            case '8':
                dbl_two += (8 / apow(10, i+1));
                break;
            case '9':
                dbl_two += (9 / apow(10, i+1));
                break;
            default:
                // invalid number !
                return 0;
        }
    }

    // STEP 3: Return the converted string as a double:
    dbl_final = dbl_one + dbl_two;
    return dbl_final;
}

/* This function 'apow' raises x to the power of y, it's a dependency of 'stod' */
double apow(const float &x, int y)
{
    double result = 1;
    if(y == 0)
        return result;

    if(y < 0)
    {
        y = -y;
        for(int i = 0; i < y; i++)
            result = result * x;
        return 1/result;
    }

    for(int i = 0; i < y; i++)
        result = result * x;

    return result;
}
3
Contributors
6
Replies
8
Views
8 Years
Discussion Span
Last Post by mvmalderen
0

I know this can also be achieved using string streams (in a few lines of code), but my purpose was to do it without ...
I just tried to avoid as much standard C++ functions as I could ...
Off course this was only to test my programming skills and I know some of you are maybe saying that I'm reinventing the wheel, but it was only a test ...

0

Or simply use the atof function :) but I see nothing wrong in reinventing the wheel too.

Lines 71 to 106 can be changed to:

if ( isdigit(strInput[i]) ) {
  dbl_one += (strInput[i] - '0') * apow(10, (nums_before_dec - i));
} else {
  return 0;
}

Nice snippet.

0

Hey tux4life,

to reiterate William's comment, remember that chars (in single quotes) are just numbers, so you don't need big if's and switches to determine them.

To know if a char's a number, try something like:

if (chr >= '0' && chr <= '9')
{
    cout << "It's a number!";
}

So, as William said, if you do "chr - '0'" you'll get the actual numeric value of the char.

Reinventing the wheel is a fine way to think about what the standard functions do - as opposed to assuming they're magically and don't cost anything ;)

0

That's why I like this forum: You post your code, people give their opinion (+suggestions) about your code, you can make your code better/more efficient/shorter, and everyone has profit ...

Thank you for your replies !
I have learnt some useful things, I'll consider changing my code (bearing your suggestions in mind) ...

BTW: Where do I have to post my changed code ?

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.