На этом шаге мы рассмотрим особенности задания и использования таких массивов.
Создадим программу, которая вводит файл с клавиатуры и подсчитывает, сколько раз в нем встречается каждая из цифр от 0 до 9. Если использовать тот опыт, который мы получили в предыдущих шагах, то для составления такой программы нам потребуется объявить десять счетчиков, в каждом из которых станем накапливать данные о том, сколько раз встретилась каждая цифра. Первый счетчик - для накапливания данных о количестве имеющихся в файле нулей, второй - для единиц и т. д.
А представим себе, что надо подсчитать количество каких-то объектов, которых, скажем, сто, и каждый может встречаться в файле разное количество раз. Надо было бы объявить сто счетчиков? Это очень неудобно. Для нашей цели удобнее воспользоваться конструкцией языка С, которая называется "массив".
Массив - это множество однотипных данных, объединенных под одним именем. Объявляется массив данных так:
<Тип данных в массиве> <Имя массива> [Количество элементов массива];
Последнее значение должно быть целым числом без знака. Например, массив 100 целых чисел можно объявить как int m[100]; массив символов - как char s[20]. Так как элементы массива располагаются в памяти последовательно друг за другом, то массив символов - это не что иное, как строка символов. Причем в языке С принято, что строка символов обязательно оканчивается признаком конца, которым служит символ с кодом \0. Если мы сами формируем символьный массив, то сами же должны позаботиться о том, чтобы его последним элементом был символ \0, иначе такую строку, полученную с помощью массива, никогда не распознает ни одна стандартная программа.
Как "доставать" элементы из описанной выше конструкции?
Если имеем, например, массив чисел int m[100];, то любой его элемент - это m[i];, где i - номер элемента (i=0, l, ..., 99).
Видим, что нумерация элементов начинается с нуля: порядковый номер первого элемента массива - 0, второго - 1 и т. д. Порядковый номер элемента массива называют индексом.
Чтобы массив инициализировать, т. е. придать его элементам какие-то значения, надо придать соответствующие значения каждому элементу массива.
Если имеем массив int m[2];, то следует написать, например: m[0]=1; m[1]=8;.
Этот же эффект получим, если напишем: int m[2] = {1, 8};. Для символьного массива char s[3]; можно писать либо так:
s[0]='a'; s[l]='b'; s[2]='c';,
char s[3]={'a','b','с'};,
s[3]="abc";.
Коль скоро мы заговорили о символах, то сделаем еще одно замечание. Если в переменной с находится символ цифры (точнее - код цифры), то выражение с-'0' дает значение самого числа, код которого находится в с.
Действительно: таблица кодов ASCII построена так, что коды всех символов английского алфавита расположены в ней по возрастанию. За кодом нуля идет код единицы (т. е. разность между кодом нуля и кодом единицы равна единице). За кодом единицы следует код двойки. Разность между кодом двойки и кодом единицы тоже равна единице. Но разность между кодом двойки и кодом нуля равна двум и т. д. Следовательно, разность между кодом числа i и кодом нуля равна числу i. Итак, составим программу, подсчитывающую количество нулей в строке символов, количество единиц и т. д.
Наша программа будет выглядеть так, как показано ниже:
// Massiv.cpp: главный файл проекта. #include "stdafx.h" #include <clocale> //обязательно для функции setlocale() using namespace System; #include <conio.h> // для getch() #include <stdio.h> // для getchar(), putchar(), printf() #define EOF -1 // признак конца файла Ctrl+Z #define MAXIND 10 //количество элементов массива int main() { setlocale(LC_ALL,"Russian"); //функция setlocale() с аргументами //для корректного вывода кириллицы int c; //для ввода символа int nd[MAXIND]; /*для подсчета количества обнаруженных в файле цифр: в nd[0] будет накапливаться количество встреченных нулей, в nd[l] - единиц, в nd[2] - двоек и т. д.*/ int i; for(i=0; i<MAXIND; i++) nd[i]=0; /*обнуление элементов массива - заготовка их под счетчики*/ printf("Задайте строку и нажмите Enter, Ctrl+Z - завершение работы >\n"); while((c=getchar()) != EOF) if(c >= '0' && c <= '9') ++nd[c-'0']; //накопление в счетчике printf("Количество цифр:\n"); for(i=0; i<MAXIND; i++) printf("цифра i=%d встретилась %d раз\n", i,nd[i]); _getch(); /*вводит символ, но без эхо-сопровождения (для организации задержки экрана) */ return 0; }
Директивой препроцессора #define мы определили символическую константу MAXIND, с помощью которой задаем (и легко можем изменять) размерность массива nd[], элементами которого мы воспользовались в качестве счетчиков. Признаком конца файла служит нажатие комбинации клавиш Ctrl+Z. Вначале все счетчики (т. е. элементы массива) обнуляются, чтобы в них накапливать по единице, если встретится соответствующая цифра. Обнуление происходит в цикле с помощью конструкции for. Цикл завершится, если нарушится условие продолжения цикла: номер элемента массива (им является значение переменной i) станет равным количеству элементов.
Далее идет уже знакомый нам цикл ввода символов, в котором проверяется, входит ли код каждого введенного символа в диапазон кодов от нуля до девятки. Если код введенного символа входит в диапазон кодов цифр, т. е. соответствует искомым цифрам, то в соответствующий элемент массива nd[] добавляется единица.
Результат работы программы приведен на рисунке 1.
Рис.1. Результаты работы программы
Заметим, что тело цикла while содержит всего одну конструкцию (if), и потому не ограничено фигурными скобками. После обнаружения символа конца файла (комбинация клавиш Ctrl+Z) происходит поэлементный вывод содержимого массива на устройство вывода. Здесь (так же, как и при инициализации) организован цикл с помощью for, телом которого является функция printf().
На следующем шаге мы рассмотрим многомерные массивы (массивы массивов).