С этого шага мы начинаем знакомиться с организацией и использованием
массивов.
Массив представляет собой последовательность элементов одного типа. Каждому элементу массива соответствует индекс - целое неотрицательное число, определяющее его номер в последовательности. Первому элементу массива соответствует индекс 0. Элементы массива размещаются в памяти последовательно, друг за другом, как показано на следующем рисунке:
Рис.1. Схема размещения в памяти элементов массива
b
При определении массива ему выделяется память так же, как массивам других алгоритмических языков. Но как только память для массива выделена, имя массива воспринимается как константный указатель того типа, к которому отнесены элементы массива. Однако это справедливо не всегда. Например, при использовании имени массива в операции sizeof, ее результатом является размер в байтах участка памяти, выделенного не для указателя, а для массива в целом. Исключением является и применение операции & (получение адреса) к имени массива. Результат операции - адрес начального (с нулевым индексом) элемента массива. В остальных случаях значением имени является адрес первого элемента массива, которое нельзя изменить.
Для создания массива компилятору необходимо знать тип данных и требуемый класс памяти, т.е. то же самое, что и для простой переменной (называемой скалярной). Кроме того, должно быть известно, сколько элементов имеет массив. Определение одномерного массива имеет вид:
<тип элементов массива> <имя массива> [<количество элементов в массиве>];.
Массивы могут иметь те же типы и классы памяти, что и простые переменные. В некоторых случаях допустимо описание массива без указания количества его элементов, то есть без константного выражения в квадратных скобках. Например: extern unsigned long UL[]; является описанием внешнего массива, который определен в другой части программы, где ему выделена память и (возможно) присвоены начальные значения его элементам. Приведем еще несколько примеров описания массивов:
char alpha[26]; //Внешний массив, содержащий 26 символов. main () { static int nan[22]; //Статический массив, содержащий 22 целых числа. extern char alpha[]; //Внешний массив, размер его указан выше. float a[15]; //Автоматический массив, содержащий 15 //вещественных чисел. }
В языке C++ определены только одномерные массивы. Многомерные массивы строятся на основе рекурсивного правила, согласно которому элементом массива может быть массив. Таким образом, в языке C++ двумерный массив (матрица) - это одномерный массив, каждый элемент которого является одномерным массивом.
При определении массива может выполняться его инициализация, то есть элементы массива получают конкретные значения. Инициализация выполняется по умолчанию, если массив статический или внешний. В этих случаях всем элементам массива компилятор автоматически присваивает нулевые значения. Явная инициализация элементов массива разрешена только при его определении и возможна двумя способами: либо с указанием размера массива в квадратных скобках, либо без явного указания (без конкретного выражения) в квадратных скобках, например:
char СН[ ] = { 'А', 'В', 'С', 'D'}; // Массив из 4 элементов. int pr[6]= {10,20,30,40}; // Массив из 6 элементов. char St[ ] = "ABCD"; // Массив из 5 элементов (включая нулевой элемент).
#include <iostream.h> int n=5; int nd[5] = { 0,1,2,3,4 }; /* Инициализация целочисленного */ /* массива внешнего класса памяти */ main () { for (int i=0; i<=n; i++) cout << "i=" << i << " nd[i]=" << nd[i] << endl; }
Следующие примеры являются ошибочными:
float A[ ]; // Отсутствует размер массива. double b[4] = {1,2,3,4,5,6,7,8}; // Количество элементов //не совпадает с размером массива.
Количество элементов массива CH компилятор определяет по числу начальных значений в списке инициализации, помещенном в фигурных скобках при определении массива. В массиве pr шесть элементов, но только первые четыре из них явно получают начальные значения. При отсутствии константного выражения в квадратных скобках список начальных значений в определении массива обязателен. Если размер массива явно задан, то количество элементов в списке начальных значений не должно превышать размера массива.
В тех случаях, когда массив не определяется, а описывается, список начальных значений задавать нельзя. В описании массива может отсутствовать и его размер:
extern float E[ ]; // Правильное описание внешнего массива.
Предполагается, что в месте определения массива для него выделена память и выполнена инициализация.
Элементы массива можно задавать в цикле при выполнении программы.
#include <iostream.h> main () { int score[10]; /* Ввод элементов массива. */ for (int i=0; i<=9; i++) { cout << i+1 << "-й элемент: "; cin >> score[i]; } /* Проверка правильности ввода. */ cout << "Введены следующие значения:\n"); for (i=0; i<=9; i++) cout << score[i] << " "; cout << endl; }
Имя массива является указателем-константой, значением которой служит адрес первого элемента массива (с индексом 0). Таким образом, доступ к первому элементу массива может быть осуществлен так:
<имя массива>[0] или *<имя массива> .
В общем случае доступ к заданному элементу массива можно осуществить двумя способами:
<имя массива>[<номер элемента>] или *(<имя массива>+<номер элемента>).
Проиллюстрируем различные способы доступа к элементам массива.
#include <iostream.h> void main() { char x[]="Пример строки"; int i=0; cout<< "\n Вывод первого символа строки (1 способ): "<< x[0]; //1 cout<< "\n Вывод первого символа строки (2 способ): "<< *x; //2 cout<< "\n Вывод строки без цикла (1 способ): "<< x; //3 cout<< "\n Вывод строки без цикла (2 способ): "<< &x[0]; //4 cout<< "\n Вывод строки с циклом (1 способ): "; //5 while (x[i]!='\0') cout << x[i++]; cout<< "\n Вывод строки с циклом (2 способ): "; //6 i=0; while (*(x+i)!='\0') cout << *(x+i++); cout<<"\n Вывод строки с циклом (3 способ): "; //7 i=0; while (i[x]!='\0') cout << i++[x]; }
Прокомментируем текст приведенной программы.
В заключение отметим, что в языке C++ нет специального типа днных "строка". Вместо этого каждая символьная строка в памяти компьютера представляется в виде одномерного массива типа char, последним элементом которого является символ '\0'. Изображение строковой константы может использоваться по-разному. Если строка применяется для инициализации массива типа char, например, так: char array[ ] = "инициализирующая строка";, то адрес первого элемента строки становится значением указателя-константы (имени массива) array. Если строка используется для инициализации указателя типа char *: char *pointer = "инициализирующая строка" ;, то адрес первого элемента строки становится значением указателя-переменной pointer. Если использовать строку в выражении, где разрешено применять указатель, то используется адрес первого элемента строки:
char * string; string = "строковый литерал";
В данном примере значением указателя string будет не вся строка
"строковый литерал",
а только адрес ее первого элемента.
На следующем шаге мы продолжим изучение массивов, в частности,
остановимся на
многомерных массивах.