C - manually parsing char* into integer I'm trying to parse a char* into an int without using atoi(). I walk through the string, check if it's a valid digit, then add that digit to my integer by multiplying by 10 and adding the digit. I am not accepting negative integers.

Here's the code I'm using:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

#define TRUE  1
#define FALSE 0

int main(int argc, char *argv[]) {
    if (argc &lt; 2)
        exit(1);


    char *p = argv[1];

    int amount = 0;
    int len = strlen((const char*) argv[1]); // calculate len beforehand
    int contin = TRUE;
    for (int i = 0; contin &amp;&amp; i &lt; len; ++i, ++p) {
        switch (*p) {
        case '0':
            amount = (amount * 10);
            break;
        case '1':
            amount = (amount * 10) + 1;
            break;
        case '2':
            amount = (amount * 10) + 2;
            break;
        case '3':
            amount = (amount * 10) + 3;
            break;
        case '4':
            amount = (amount * 10) + 4;
            break;
        case '5':
            amount = (amount * 10) + 5;
            break;
        case '6':
            amount = (amount * 10) + 6;
            break;
        case '7':
            amount = (amount * 10) + 7;
            break;
        case '8':
            amount = (amount * 10) + 8;
            break;
        case '9':
            amount = (amount * 10) + 9;
            break;
        default:
            contin = FALSE;
            break;
        }
    }

    fprintf(stdout, "amount: %i\n", amount);
    return 0;
}


...which works nicely. But, is there a better/more idiomatic way to do this?

EDIT: Thanks to Groo, I'm able to remove the giant switch statement:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

#define TRUE  1
#define FALSE 0

int main(int argc, char *argv[]) {
    if (argc &lt; 2)
        exit(1);


    char *p = argv[1];

    int amount = 0;
    int len = strlen((const char*) argv[1]); // calculate len beforehand
    int contin = TRUE;
    for (int i = 0; contin &amp;&amp; i &lt; len; ++i, ++p) {
        /* handle negative integers */
        if (*p == '-' &amp;&amp; i == 0) {
            fprintf(stderr, "negative integers are invalid.\n");
            exit(1);
        }

        if (*p &gt; 0x2F &amp;&amp; *p &lt; 0x3A)
            amount = (amount * 10) + (*p - '0');
        else {
            contin = FALSE;
            --p;
        }
    }

    fprintf(stdout, "amount: %i\n", amount);
    return 0;
}
```
Since command line arguments are null-terminated, we can avoid strlen() entirely by just running through the string until we hit '\0'; this also gets rid of contin and i
(*p &gt; 0x2F &amp;&amp; *p &lt; 0x3A) isn't very obvious, I'd just use '0' and '9' to make it easier to understand the intention and to be consistent with the rest of the code
You could use EXIT_SUCCESS and EXIT_FAILURE instead of 0 and 1 respectively
For consistency, I'd replace your call to exit() with a simple return 
I'd remove the amount: part of the print; it should be clear from the context (running this program) what the output actually is; this would also make processing the output easier


Putting it all together, we end up with this short piece:

int main(int argc, char *argv[]) {
    if (argc &lt; 2)
        return EXIT_FAILURE;

    char *p = argv[1];
    int amount = 0;

    while (*p) {
        if (*p &lt; '0')
            return EXIT_FAILURE;
        if (*p &gt; '9')
            return EXIT_FAILURE;

        amount = (amount * 10) + (*p++ - '0');
    }

    fprintf(stdout, "%i\n", amount);
    return EXIT_SUCCESS;
}


Note, however, that this doesn't account for:


negative numbers (starting with a -)
positive numbers starting with a +
any leading whitespace


Furthermore:


If the input starts with a number and has a letter following sometimes later, it will break out and print the number it has found until then; but if the first character found is a letter, the program prints 0 and reports success, which could be by design, but could also be considered a bug
The use of *p++ can be a bit dangerous if this was code shared with less experienced programmers, as simply changing it to ++*p would increase the value pointed to instead of the pointer itself; changing it to *(p++) might help
While this comes down to taste, I would argue to always use curly braces, even for one-liners: otherwise, adding another line later would break the code; also consistency is a plus
Adding support for leading whitespace is easy and also supports my previous point, as missing brackets would break the program:


    if (*p == ' ') {
        *p++;
        continue;
    }



If you don't want to implement support for negative numbers, it might be reasonable to change the type of amount to unsigned or - even better - unsigned long long, which would give you a possible range of [0, +18446744073709551615]
Naive handling of negative integers would be quite easy to implement (but note Roland's answer for caveats with this):


    int sign = 1;

    if (*p == '-') {
        sign = -1;
        *p++;
    }

    /* loop */

    amount *= sign;