Подсчет цифр, символов пустого пространства, остальных
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', то есть текстовое '1', то десятичное значение будет его chr-код, т.е. 49. Для того, чтобы попасть в индекс [1] надо из 49 вычесть 48, или его asc-символ '0'. И так для любой текстовой цифры. Советую погуглить "ASCII".
Следуя тому, что любой символ имеет свой 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) с текущем индексом увеличиваем, вот и все, друг.