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

Массивы в языке C++ могут быть многомерными. Объявление многомерного массива имеет следующий формат:

<Тип> <Переменная>[<Количество элементов1>]...[<Количество элементовN>];

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

<Тип> <Переменная>[<Количество строк>][<Количество столбцов>];

Пример объявления двумерного массива, содержащего две строки и четыре столбца:

int arr[2][4]; // Две строки из 4-х элементов каждая

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

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

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

int arr[2][4] = {
   {1, 2, 3, 4},
   {5, 6, 7, 8}
};
for (int i = 0, j = 0; i < 2; ++i) {
   for (j = 0; j < 4; ++j) {
      std::cout << arr[i][j] << ' ';
   }
   std::cout << std::endl;
}

Результат выполнения:

1 2 3 4 
5 6 7 8 

Если при объявлении производится инициализация, то количество строк можно не указывать, оно будет определено автоматически:

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

Получить или задать значение элемента можно указав два индекса (не забывайте, что нумерация начинается с нуля):

int arr[2][4] = {
   {1, 2, 3, 4},
   {5, 6, 7, 8}
};
std::cout << arr[0][0] << std::endl; // 1
std::cout << arr[1][0] << std::endl; // 5
std::cout << arr[1][3] << std::endl; // 8

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

const int ROWS = 4;    // Количество строк
const int COLUMNS = 5; // Количество столбцов
int i = 0, j = 0, n = 1, arr[ROWS][COLUMNS];
// Нумеруем все элементы массива
for (i = 0; i < ROWS; ++i) {
   for (j = 0; j < COLUMNS; ++j) {
      arr[i][j] = n;
      ++n;
   }
}
// Выводим значения
for (i = 0; i < ROWS; ++i) {
   for (j = 0; j < COLUMNS; ++j) {
      std::cout.width(3);       // Ширина поля
      std::cout << arr[i][j];
   }
   std::cout << std::endl;
}

Результат:

  1  2  3  4  5
  6  7  8  9 10
 11 12 13 14 15
 16 17 18 19 20

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

const int ROWS = 4, COLUMNS = 5;
int arr[ROWS][COLUMNS] = {
   {1, 2, 3, 4, 5},
   {6, 7, 8, 9, 10},
   {11, 12, 13, 14, 15},
   {16, 17, 18, 19, 20}
};
for (int *p = arr[0], *p2 = arr[0]+ROWS*COLUMNS; p < p2; ++p) {
   std::cout << *p << std::endl;
}

Обратите внимание на инициализацию указателя:

int *p = arr[0]

Мы сохраняем в указателе адрес первого элемента массива. Эта инструкция эквивалентна такой инструкции:

int *p = &arr[0][0]

Следующая инструкция является неверной, так как arr содержит адрес массива, а не адрес первого элемента двумерного массива:

int *p = arr

Чтобы такая инициализация указателя стала корректной нужно объявить указатель следующим образом:

int (*p)[COLUMNS] = arr;
std::cout << p[0][0] << std::endl; // 1
std::cout << p[3][4] << std::endl; // 20

Можно также объявить указатель на двумерный массив, в этом случае при инициализации перед названием двумерного массива нужно указать оператор &:

int (*p)[ROWS][COLUMNS] = &arr;
std::cout << (*p)[0][0] << std::endl; // 1
std::cout << (*p)[3][4] << std::endl; // 20

При динамическом создании двумерного массива вначале создается массив указателей (см. листинг 3.19):

int **p = (int **) std::calloc(ROWS, sizeof(int*));

Затем в этот массив добавляются строки:

for (i = 0; i < ROWS; ++i) {
   p[i] = (int *) std::calloc(COLUMNS, sizeof(int));
}

Сохранить значение в элементе массива можно так:

p[i][j] = n++;

или так:

*(*(p + i) + j) = n++;

Получить значение и вывести его можно так:

std::cout << p[i][j] << ' ';

или так:

std::cout << *(*(p + i) + j) << ' ';

После окончания работы с динамическим двумерным массивом нужно не забыть освободить память:

for (int i = 0; i < ROWS; ++i) {
   std::free(p[i]);
}
std::free(p);
p = nullptr;                         // Обнуляем указатель

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов