3

I am confused with this line:

sum += a[s[i] - '0']; 

To give some context, this is the rest of the code:

#include <iostream>

using namespace std;

int main() {

    int a[5];
    for (int i = 1; i <= 4; i++)
        cin >> a[i];
    string s;
    cin >> s;
    int sum = 0;
    for (int i = 0; i < s.size(); i++)
        sum += a[s[i] - '0'];
    cout << sum << endl;
    return 0;
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
Zachary
  • 31
  • 1
  • 2
    `s[i]-'0'` converts a character to the corresponding number. – Thomas Sablik Apr 02 '20 at 14:48
  • the '0' is a char value 48, the input is offset by that value, and the acual array starts with subscript 0. – Cee McSharpface Apr 02 '20 at 14:49
  • 2
    fwiw, this is quite dangerous code. If user types wrong input (which can be done easily) the code has undefined behavior and anything can happen – 463035818_is_not_an_ai Apr 02 '20 at 14:51
  • @TedLyngmo, though I understand the close vote (the question clearly points to it), there are some other issues in the code, which makes this question not 100% trivial. – anastaciu Apr 02 '20 at 15:36
  • @CeeMcSharpface -- regardless of the character encoding, `ch - '0'` converts a digit to its numeric value. That's true even when `'0'` is not 48. There are systems in existence that don't use ASCII. – Pete Becker Apr 02 '20 at 16:18

2 Answers2

6

- '0' (or less portable - 48, for ASCII only) is used to manually convert numerical characters to integers through their decimal codes, C++ (and C) guarantees consecutive digits in all encodings.

In EBCDIC, for example, the codes range from 240 for '0' to 249 for '9', this will work fine with - '0', but will fail with - 48). For this reason alone it's best to always use the - '0' notation like you do.

For an ASCII example, if '1''s ASCII code is 49 and '0''s ASCII code is 48, 49 - 48 = 1, or in the recommended format '1' - '0' = 1.

So, as you probably figured out by now, you can convert all the 10 digits from characters using this simple arithmetic, just subtracting '0' and in the other direction you can convert all digits to it's character encoding by adding '0'.

Beyond that there are some other issues in the code:

  • The array does not start being populated at index 0, but at index 1, so if your string input is, for instance, "10" the sum will be a[1] + a[0], but a[0] has no assigned value, so the behaviour is undefined, you need to wach out for these cases.
for (int i = 0; i < 5; i ++)
    cin >> a[i];

would be more appropriate, indexes from 0 to 4, since the array has 5 indexes, if you want input numbers from 1 to 5, you can subract 1 from the to the index later on.

  • As pointed out in the comment section, a bad input, with alpabetic characters, for instance, will also invoke undefined behaviour.
anastaciu
  • 23,467
  • 7
  • 28
  • 53
3

From the C++ Standard (2.3 Character sets)

  1. ... In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.

So if you have a character for example '4' then to get value 4 you can write '4' - '0'.

If you will write like for example

sum += a[s[i]];

where i is the character '0' then in fact you will have either

sum += a[s[48]];

if the ASCII coding is used or

sum += a[s[240]];

if the EBCDIC coding is used.

The reversed operation of getting a character from a digit you can write for example

int digit = 4;
char c = digit + '0';

Pay attention to that indices of arrays in C++ start from 0.

Thus this loop

for (int i = 1; i <= 4; i ++)
    cin >> a[i];

should be written like

for (int i = 0; i < 5; i ++)
    cin >> a[i];

Also to avoid such an error you could use the range based for loop like

for ( auto &item : a ) std::cin >> item;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335