Подсчет цифр, символов пустого пространства, остальных

stack overflow. Я сюда пишу по вопросу, что никак не могу понять данный код. А именно, выражение ++ndigit[c-'o']; (то есть выражение я понимаю, а саму логику, а также сам смысл не понимаю). К примеру переменная c является '1', условие срабатывает и текущий символ в переменной c преобразовывается в целочисленное число ('0' (c - '0'), и вот, как раз-таки дальше, я не как не могу разобраться с этим выражением, т.е. для чего автор (который написал данный код: книга K&R) увеличивает на единицу текущий индекс числа (под переменной c) и затем записывает это число в индекс, который расположен под этой же переменной c. Логика абсолютно не понятна, потому я и обращаюсь за помощью в stack overflow.

Ниже я написал код, чтобы вы поняли, о чем идет речь:

#include <stdio.h>
int main(void)
{
    int c, i, nwhite, nother;
    int ndigit[10];

    nwhite = nother = 0;
    for(i = 0; i < 10; ++i){
        ndigit[i] = 0;
    }
    while((c = getchar()) != EOF)
        if(c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        else if(c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else 
            ++nother;
    
    printf("digits =");
    for(i = 0; i < 10; ++i)
        printf(" %i", ndigit[i]);
    printf(", white space = %i, other = %i\n", nwhite, nother);
}

Также, хотел бы еще спросить, почему, когда я ввожу в потоке ввода цифры поочередно: 1 2 3 4 5 6 7 8 9 0 и далее прекращаю поток (Ctrl + C (на windows),тем самым символ равняется EOF и поток ввода прекращает свою работу, то далее, в потоке вывода отображается вот что: digits = 1 1 1 1 1 1. А если писать в потоке ввода цифры без пробелов, результат получается таким же, но только уже не 6 единиц, а 5. То есть вообще не понятно, как получается такой результат этого кода.

Вопроса всего два, поэтому, если вам будет не сложно, объясните мне пожалуйста, в чем же дело этого кода и его результат. И что за выражение ++ndigit[c-'0'], который написал автор (или авторы, но не суть) книги K&R.


Ответы (3 шт):

Автор решения: валаша валашевич

Программа считает, сколько раз встретились 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ' ', '\n', '\t' и другие символы при воде.

Таблица символов ASCII: https://en.cppreference.com/w/cpp/language/ascii .

Для EOF на windows надо нажать Ctrl + z потом enter.

#include <stdio.h>
#include <iostream>
int main (void) {
    using namespace std;
    int c, i, nwhite, nother;
    int ndigit[10];
    nwhite = nother = 0;
    for (i = 0; i < 10; ++i){
        ndigit [i] = 0;
    }
    cout << "(char) 48: " << (char) 48 << endl;//48 - это номер символа 0 в таблице символов ASCII.
    cout << "(int) \'\\0\': " << (int) '\0' << endl;
    cout << "(char) 0: " << (char) 0 << endl;
    cout << "(int) \'0\': " << (int) '0' << endl;
    while ((c = getchar ()) != EOF)
        if (c >= '0' && c <= '9')
            /*
            Вели 2, у 2 номер 50, 50 - 48 = 2.
            Обращаемся по индексу 2 к переменной, которая символизирует количество введённых двоек, и прибавляем к количеству 1.
            */
            ++ndigit [c - '0'];
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;//Прибовляем 1 к количеству символов ' ', '\n', '\t'.
        else 
            ++nother;//Прибовляем 1 к количеству остальных символов.
    
    printf ("digits =");
    for(i = 0; i < 10; ++i)
        printf(" %i", ndigit[i]);
    printf(", white space = %i, other = %i\n", nwhite, nother);
}

Статьи:

  1. https://www.geeksforgeeks.org/c-program-for-char-to-int-conversion/
  2. https://www.geeksforgeeks.org/c-program-for-int-to-char-conversion/
  3. Си: проблема с getchar() и EOF(^Z) в Windows консоли
→ Ссылка
Автор решения: Solt

Если с='1', то есть текстовое '1', то десятичное значение будет его chr-код, т.е. 49. Для того, чтобы попасть в индекс [1] надо из 49 вычесть 48, или его asc-символ '0'. И так для любой текстовой цифры. Советую погуглить "ASCII".

→ Ссылка
Автор решения: Lorraineboza Wilelkwile

Следуя тому, что любой символ имеет свой ascii-код, то можно понять, что также и '1' и '2' и так далее, имеют также свои коды. У символа '1' код равен 49. И так как у '0' код равняется 48, то если вычесть из '1' символ '0', в результате мы получим 1(49 ('1') - 48('0') = 1) и уже типа int, а не типа char (иными словами, мы переводим цифру типа char в цифру типа int). То же самое и с '2' и с '3' ... до '9' . И затем, если нам встречается символ '1', то мы его переводим (тем самым выполняя стандартную операцию перевода: c - '0' или c - 48 (одно и то же)) и далее этот элемент (коотрый мы перевели) массива (ndigit) с текущем индексом увеличиваем, вот и все, друг.

→ Ссылка