Шаг 23.
Microsoft Visual C++ 2010. Язык С/С++.
Работа с массивами. Одномерные массивы

    На этом шаге мы рассмотрим особенности задания и использования таких массивов.

    Создадим программу, которая вводит файл с клавиатуры и подсчитывает, сколько раз в нем встречается каждая из цифр от 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";.


   Примечание. В одинарных кавычках 'b' записывают символы, в двойных кавычках - строки символов, потому что последний символ строки символов - признак конца строки '\0': когда мы пишем строку в двойных кавычках, компилятор по этому признаку сам формирует признак конца строки - символ '\0'. Поэтому 'b' - это один символ, а "b" - два символа.

    Коль скоро мы заговорили о символах, то сделаем еще одно замечание. Если в переменной с находится символ цифры (точнее - код цифры), то выражение с-'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().

    На следующем шаге мы рассмотрим многомерные массивы (массивы массивов).




Предыдущий шаг Содержание Следующий шаг