Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
85
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

115

3.9.1. Многомерные массивы

В С++ есть возможность использовать многомерные массивы, при объявлении которых

необходимо указать правую границу каждого измерения в отдельных квадратных скобках. Вот определение двумерного массива:

int ia[ 4 ][ 3 ];

Первая величина (4) задает количество строк, вторая (3) – количество столбцов. Объект ia определен как массив из четырех строк по три элемента в каждой. Многомерные

int ia[ 4 ][ 3 ] = {

{0, 1, 2 },

{3, 4, 5 },

{6, 7, 8 },

{9, 10, 11 }

массивы тоже могут быть инициализированы:

};

Внутренние фигурные скобки, разбивающие список значений на строки, необязательны и используются, как правило, для удобства чтения кода. Приведенная ниже инициализация в точности соответствует предыдущему примеру, хотя менее понятна:

int ia[4][3] = { 0,1,2,3,4,5,6,7,8,9,10,11 };

Следующее определение инициализирует только первые элементы каждой строки. Оставшиеся элементы будут равны нулю:

int ia[ 4 ][ 3 ] = { {0}, {3}, {6}, {9} };

Если же опустить внутренние фигурные скобки, результат окажется совершенно иным. Все три элемента первой строки и первый элемент второй получат указанное значение, а остальные будут неявно инициализированы 0.

int ia[ 4 ][ 3 ] = { 0, 3, 6, 9 };

При обращении к элементам многомерного массива необходимо использовать индексы для каждого измерения (они заключаются в квадратные скобки). Так выглядит

int main()

{

const int rowSize = 4; const int colSize = 3;

int ia[ rowSize ][ colSize ];

for ( int = 0; i < rowSize; ++i ) for ( int j = 0; j < colSize; ++j )

ia[ i ][ j ] = i + j j;

инициализация двумерного массива с помощью вложенных циклов:

}

С++ для начинающих

116

Конструкция

ia[ 1, 2 ]

является допустимой с точки зрения синтаксиса С++, однако означает совсем не то, чего ждет неопытный программист. Это отнюдь не объявление двумерного массива 1 на 2. Агрегат в квадратных скобках это список выражений через запятую, результатом которого будет последнее значение 2 (см. оператор запятаяв разделе 4.2). Поэтому объявление ia[1,2] эквивалентно ia[2]. Это еще одна возможность допустить ошибку.

3.9.2. Взаимосвязь массивов и указателей

Если мы имеем определение массива:

int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };

то что означает простое указание его имени в программе?

ia;

Использование идентификатора массива в программе эквивалентно указанию адреса его

ia;

первого элемента:

&ia[0]

// оба выражения возвращают первый элемент

*ia;

Аналогично обратиться к значению первого элемента массива можно двумя способами: ia[0];

Чтобы взять адрес второго элемента массива, мы должны написать:

&ia[1];

Как мы уже упоминали раньше, выражение

ia+1;

также дает адрес второго элемента массива. Соответственно, его значение дают нам

*(ia+1);

следующие два способа: ia[1];

С++ для начинающих

117

Отметим разницу в выражениях:

*ia+1

и

*(ia+1);

Операция разыменования имеет более высокий приоритет, чем операция сложения (о приоритетах операций говорится в разделе 4.13). Поэтому первое выражение сначала разыменовывает переменную ia и получает первый элемент массива, а затем прибавляет к нему 1. Второе же выражение доставляет значение второго элемента.

Проход по массиву можно осуществлять с помощью индекса, как мы делали это в

#include <iostream> int main()

{

int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 }; int *pbegin = ia;

предыдущем разделе, или с помощью указателей. Например:

while ( pbegin != pend ) { cout << *pbegin <<; ++pbegin;

int *pend = ia + 9;

}

Указатель pbegin инициализируется адресом первого элемента массива. Каждый проход по циклу увеличивает этот указатель на 1, что означает смещение его на следующий элемент. Как понять, где остановиться? В нашем примере мы определили второй указатель pend и инициализировали его адресом, следующим за последним элементом массива ia. Как только значение pbegin станет равным pend, мы узнаем, что массив кончился.

Перепишем эту программу так, чтобы начало и конец массива передавались параметрами

#inc1ude <iostream>

void ia_print( int *pbegin, int *pend )

{

while ( pbegin != pend ) { cout << *pbegin << ' '; ++pbegin;

}

}

int main()

{

int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 }; ia_print( ia, ia + 9 );

в некую обобщенную функцию, которая умеет печатать массив любого размера:

}

С++ для начинающих

118

Наша функция стала более универсальной, однако, она умеет работать только с массивами типа int. Есть способ снять и это ограничение: преобразовать данную

#inc1ude <iostream>

template <c1ass e1emType>

void print( elemType *pbegin, elemType *pend )

{

while ( pbegin != pend ) { cout << *pbegin << ' '; ++pbegin;

}

функцию в шаблон (шаблоны были вкратце представлены в разделе 2.5):

}

 

 

int main()

 

 

{

{ 0, 1, 1,

2, 3, 5, 8, 13, 21 };

int ia[9] =

double da[4]

= { 3.14,

6.28, 12.56, 25.12 };

string sa[3]

= { "piglet", "eeyore", "pooh" };

print( ia, ia+9 ); print( da, da+4 ); print( sa, sa+3 );

Теперь мы можем вызывать нашу функцию print() для печати массивов любого типа:

}

Мы написали обобщенную функцию. Стандартная библиотека предоставляет набор обобщенных алгоритмов (мы уже упоминали об этом в разделе 3.4), реализованных подобным образом. Параметрами таких функций являются указатели на начало и конец массива, с которым они производят определенные действия. Вот, например, как выглядят

#include <a1gorithm> int main()

{

int ia[6] = { 107, 28, 3, 47, 104, 76 }; string sa[3] = { "piglet", "eeyore", "pooh" };

sort( ia, ia+6 ); sort( sa, sa+3 );

вызовы обобщенного алгоритма сортировки:

};

(Мы подробно остановимся на обобщенных алгоритмах в главе 12; в Приложении будут приведены примеры их использования.)

В стандартной библиотеке С++ содержится набор классов, которые инкапсулируют использование контейнеров и указателей. (Об этом говорилось в разделе 2.8.) В следующем разделе мы займемся стандартным контейнерным типом vector, являющимся объектно-ориентированной реализацией массива.