0

Given this implementation of atoi in C++

// A simple atoi() function
int myAtoi(char *str)
{
    int res = 0; // Initialize result

    // Iterate through all characters of input string and update result
    for (int i = 0; str[i] != '\0'; ++i)
        res = res*10 + str[i] - '0';

    // return result.
    return res;
}

// Driver program to test above function
int main()
{
    char str[] = "89789";
    int val = myAtoi(str);
    printf ("%d ", val);
    return 0;
}

How exactly does the line

res = res*10 + str[i] - '0';

Change a string of digits into int values? (I'm fairly rusty with C++ to be honest. )

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
user3708902
  • 161
  • 1
  • 2
  • 12
  • http://stackoverflow.com/questions/15598698/why-does-subtracting-0-in-c-result-in-the-number-that-the-char-is-representing – Evdzhan Mustafa Mar 07 '15 at 20:57
  • There's no reason that function should be taking a pointer to non-constant data if it doesn't modify that data. You've just forced people with a string they can't change to either copy it or insert an ugly and suspicious cast. – chris Mar 07 '15 at 21:13

4 Answers4

4

The standard requires that the digits are consecutive in the character set. That means you can use:

 str[i] - '0'

To translate the character's value into its equivalent numerical value.

The res * 10 part is to shuffle left the digits in the running total to make room for the new digit you're inserting.

For example, if you were to pass "123" to this function, res would be 1 after the first loop iteration, then 12, and finally 123.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
3

Each step that line does two things:

  1. Shifts all digit left by a place in decimal
  2. Places the current digit at the ones place

The part str[i] - '0' takes the ASCII character of the corresponding digit which are sequentially "0123456789" and subtracts the code for '0' from the current character. This leaves a number in the range 0..9 as to which digit is in that place in the string.

So when looking at your example case the following would happen:

  1. i = 0str[i] = '8': res = 0 * 10 + 8 = 8
  2. i = 1str[i] = '9': res = 8 * 10 + 9 = 89
  3. i = 2str[i] = '7': res = 89 * 10 + 7 = 897
  4. i = 3str[i] = '8': res = 897 * 10 + 8 = 8978
  5. i = 4str[i] = '9': res = 8978 * 10 + 9 = 89789

And there's your result.

sim642
  • 751
  • 7
  • 14
  • This assumes that the compilation target character set is compatible with the execution character set (locale). That's a good bet. But neither are likely to be ASCII. – Tom Blodget Mar 07 '15 at 21:21
1

The digits 0123456789are sequential in ASCII.

The char datatype (and literal chars like '0') are integral numbers. In this case, '0' is equivalent to 48. Subtracting this offset will give you the digit in numerical form.

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • 1
    '0' to '9' are sequential in all standardised character sets, not just ASCII. There are implementations that support a character set other than ASCII, for which '0' is not equal to 48, but the technique will still work. – Rob Mar 07 '15 at 21:13
1

Lets take an example:

str = "234";

to convert it into int, basic idea is to process each character of string like this:

res = 2*100 + 3*10 + 4
or
res = 0
step1: res = 0*10 + 2 = 0 + 2 = 2
step2: res = res*10 + 3 = 20 + 3 = 23
step3: res = res*10 + 4 = 230 + 4 = 234

now since each letter in "234" is actually a character, not int and has ASCII value associated with it

ASCII of '2' = 50
ASCII of '3' = 51
ASCII of '4' = 52
ASCII of '0' = 48

refer: http://www.asciitable.com/

if i had done this:

res = 0;
res = res*10 + str[0] = 0 + 50 = 50
res = res*10 + str[1] = 500 + 51 = 551
res = res*10 + str[2] = 5510 + 52 = 5562

then i would have obtained 5562, which we don't want.

remember: on using characters in arithmetic expressions, their ASCII value is used up (automatic typecasting of char -> int). Hence we need to convert character '2'(50) to int 2, which we can accomplish like this:

'2' - '0' = 50 - 48 = 2

Lets solve it again with this correction:

res = 0
res = res*10 + (str[0] - '0') = 0 + (50 - 48) = 0 + 2 = 2
res = res*10 + (str[1] - '0') = 20 + (51 - 48) = 20 + 3 = 23
res = res*10 + (str[2] - '0') = 230 + (52 - 48) = 230 + 4 = 234

234 is the required answer

rachitnaruzu
  • 128
  • 1
  • 8