Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория ответы.doc
Скачиваний:
39
Добавлен:
24.12.2018
Размер:
1.61 Mб
Скачать
  1. Структурированные типы данных: двумерные массивы. Создание и заполнение массива. Доступ к элементу массива. Основные операции с двумерным массивом.

В этой главе мы рассматриваем массивы. Массив (array) — это коллекция переменных одинакового типа, обращение к которым происходит с применением общего для всех имени. В C++ массивы могут быть одно- или многомерными, хотя в основном используются одномерные массивы. Массивы представляют собой удобное средство группирования связанных переменных.

Чаще всего используются символьные массивы, в которых хранятся строки. Как упоминалось выше, в C++ не определен встроенный тип данных для хранения строк. Поэто­му строки реализуются как массивы символов. Такой подход к реализации строк дает С++-программисту больше "рычагов" управления по сравнению с теми языками, в кото­рых используется отдельный строковый тип данных.

Двумерные массивы

В C++ можно использовать многомерные массивы. Простейший многомерный мас­сив — двумерный. Двумерный массив, по сути, представляет собой список одномерных массивов. Чтобы объявить двумерный массив целочисленных значений размером 10x20 с именем twod, достаточно записать следующее:

int twod[10][20] ;

Обратите особое внимание на это объявление. В отличие от многих других языков программирования, в которых при объявлении массива значения размерностей отделяются запятыми, в C++ каждая размерность заключается в собственную пару квадратных скобок.

Чтобы получить доступ к элементу массива twod с координатами 3,5, необходимо использовать запись twod[3] [5]. В следующем примере в двумерный массив поме­щаются последовательные числа от 1 до 12.

#include <iostream>

using namespace std;

int main() {

int t, i, num[3] [4] ;

for(t=0; t<3; ++t) {

for(i=0; i<4; ++i) {

num[t][i] = (t*4)+i+l;

cout << num[t] [i] << “ “ ;

}

cout << '\n';

}

return 0;

}

В этом примере элемент num[0] [0] получит значение 1, элемент num[0] [1] — значение 2, элемент num[0] [2] — значение 3 и т.д. Значение элемента num[2] [3] будет равно числу 12. Схематически этот массив можно представить, как показано на рис. 5.1.

В двумерном массиве позиция любого элемента определяется двумя индексами. Если представить двумерный массив в виде таблицы данных, то один индекс означает строку, а второй — столбец. Из этого следует, что, если доступ к элементам массива предоставить в порядке, в котором они реально хранятся в памяти, то правый индекс будет изменяться быстрее, чем левый.

0 1 2 3

0

1

2

3

4

1

5

6

7

8

2

9

10

11

12

Левый индекс num [1] [2] Правый индекс

Рис. 5.1. Схематическое представление массива пит

Необходимо помнить, что место хранения для всех элементов массива определяется во время компиляции. Кроме того, память, выделенная для хранения массива, используется в течение всего времени существования массива. Для определения количества байтов памяти, занимаемой двумерным массивом, используйте следующую формулу.

число байтов = число строк х число столбцов х размер типа в байтах

Следовательно, двумерный целочисленный массив размерностью 10x5 занимает в памяти 10x5x2, т.е. 100 байт (если целочисленный тип имеет размер 2 байт).

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

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

ТИП имя[размер1] [размер2] ...[размеры] ;

Например, с помощью следующего объявления создается трехмерный целочисленный массив размером 4x10x3.

int multidim[4] [10] [3] ;

Как упоминалось выше, память, выделенная для хранения всех элементов массива, используется в течение всего времени существования массива. Массивы с числом изменений, превышающим три, используются нечасто, хотя бы потому, что для их хранения требуется большой объем памяти. Например, хранение элементов четырехмерного символьного массива размером 10x6x9x4 займет 2 160 байт. А если каждую размерность увеличить в 10 раз, то занимаемая массивом память возрастет до 21 600 000 байт. Как видите, большие многомерные массивы способны "съесть" большой объем памяти, а программа, которая их использует, может очень быстро столкнуться с проблемой нехватки памяти.

Инициализация массивов

В C++ предусмотрена возможность инициализации массивов. Формат инициализации массивов подобен формату инициализации других переменных.

ТИП имя_массива [размер] = {список_значений};

Здесь элемент список_значений представляет собой список значений инициализации элементов массива, разделенных запятыми. Тип каждого значения инициализации должен быть совместим с базовым типом массива (элементом тип). Первое значение инициализации будет сохранено в первой позиции массива, второе значение — во второй и т.д. Обратите внимание на то, что точка с запятой ставится после закрывающей фигурной скобки (}).

Например, в следующем примере 10-элементный целочисленный массив инициализируется числами от 1 до 10.

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

После выполнения этой инструкции элемент i [ 0 ] получит значение 1, а элемент i [ 9 ] — значение 10.

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

char имя_массива[размер] = "строка";

Например, следующий фрагмент кода инициализирует массив str фразой "привет",

char str[7] = "привет";

Это равнозначно поэлементной инициализации.

char str[7] = {'п’, 'р', 'и', 'в', 'е', 'т', '\0'};

Поскольку в C++ строки должны завершаться нулевым символом, убедитесь, что при объявлении массива его размер указан с учетом признака конца. Именно поэтому в предыдущем примере массив str объявлен как 7-элементный, несмотря на то, что в слове "привет" только шесть букв. При использовании строкового литерала компилятор добавляет нулевой признак конца строки автоматически.

Многомерные массивы инициализируются по аналогии с одномерными. Например, в следующем фрагменте программы массив sqrs инициализируется числами от 1 до 10 и квадратами этих чисел. int sqrs[10][2] = {

  1. 1,

  2. 4,

  3. 9,

  4. 16,

  5. 25,

  6. 36,

  7. 49,

  8. 64,

  9. 81,

10, 100 };

Теперь рассмотрим, как элементы массива sqrs располагаются в памяти (рис. 5.2).

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

int sqrs[10][2] = { {1, 1}, {2, 4}, {3, 9}, (4, 16}, (5, 25},

{6, 36), {7, 49}, {8, 64}, (9, 81}, {10, 100}};

1

21

41

3

9

4

16

100

100

Правый индекс

0 1

1

0

1

2

3

4

10

Левый индекс

Рис. 5.2. Схематическое представление инициализированного массива sqrs

При использовании подгрупп инициализаторов недостающие члены подгруппы будут инициализированы нулевыми значениями автоматически.

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

#include <iostream.h>

int sqrs[10][2] = {

{1, 1},

{2, 4},

{3, 9},

{4, 16},

{5, 25},

{6, 36},

{7, 49},

{8, 64},

(9, 81}, {10, 100}

int main () {

int i, j;

cout << "Введите число от 1 до 10: ";

cin >> i;

// Поиск значения i.

for(j=0; j<10; j++)

if(sqrs[j][0]==i) break;

cout << "Квадрат числа " << i « " равен ";

cout << sqrs[j][1];

return 0; }

Глобальные массивы инициализируются в начале выполнения программы, а локальные — при каждом вызове функции, в которой они содержатся. Рассмотрим пример.

#include <iostream.h>

#include <string.h>

void fl() ;

int main() {

fl() ;

fl();

return 0; }

void fl() {

char s[80]="Эto просто тест\n";

cout << s;

strcpy(s, "ИЗМЕНЕН0\n"); // Изменяем значение строки s.

cout << s; }

При выполнении этой программы получаем такие результаты.

Это просто тест

ИЗМЕНЕНО

Это просто тест

ИЗМЕНЕНО

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

Это просто тест

"Безразмерная" инициализация массивов

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

char el [14] = "Деление на 0\n";

char e2[23] = "Конец файла\n";

char еЗ[21] = "В доступе отказано\n";

Нетрудно предположить, что вручную неудобно подсчитывать символы в каждом сообщении, чтобы определить корректный размер массива. К счастью, в C++ предусмотрена возможность автоматического определения длины массивов путем использования их «безразмерного» формата. Если в инструкции инициализации массива не указан его размер, C++ автоматически создаст массив, размер которого будет достаточным для хранения всех значений инициализаторов. При таком подходе предыдущий вариант инициализации массивов для построения таблицы сообщений об ошибках можно переписать так.

char el[] = "Деление на 0\n";

char е2[] = "Конец файла\n";

char еЗ[] = "В доступе отказано\n";

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

"Безразмерная" инициализация массивов не ограничивается одномерными массивами. При инициализации многомерных массивов вам необходимо указать все данные, за исключением крайней слева размерности, чтобы С++-компилятор мог должным образом

индексировать массив. Используя "безразмерную" инициализацию массивов, можно создавать таблицы различной длины, позволяя компилятору автоматически выделять область памяти, достаточную для их хранения.

В следующем примере массив sqrs объявляется как "безразмерный".

int sqrs[] [2] = {1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100};

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