Массивы в С++ могут быть не только одномерными, т.е. когда данные визуально выстроены в одну линию. Массивы также могут быть и двумерными, трехмерными и так далее. С++ компиляторы поддерживают как минимум 12-ти мерные массивы!!! Естественно, что такими большими массивами на практике никто не пользуется, т.к. человеку сложно их визуально представить у себя в голове, не то что написать программу, которая оперирует таким сложными массивами. На практике редко применяют массивы, более трехмерного. Одномерный - это строка, двумерный - матрица (таблица), трехмерный - куб, а вот дальше уже сложно, поэтому дальше, обычно, никто и не идет... Вот такие дела.
Двумерный массив - это так называемая матрица (или таблица), у которой есть строки и столбцы. По соглашению программистов первый индекс массива будет указывать на строки, а второй на столбцы. Вот пример объявления и инициализации двумерного массива, состоящего из трех строк и пяти столбцов.
1.int aMatrix[3][5] = {{3, 5, 5, 7, 8},
2. {4, 1, 1, 2, 9},
3. {3, 8, 8, 9, 7}};
Как видите, двумерный массив имеет два индекса (на то он, в принципе, так и называется). Сразу при объявлении мы его инициализируем целочисленными величинами. Для удобства мы их записываем в виде матрицы (таблицы): каждая строка с новой строки (их у нас 3), в каждой строке 5 столбцов.
Можно и так записать, как показано ниже. Разницы для компилятора не будет никакой. Разве лишь разница будет в визуальном восприятии для человека.
Кстати, последняя запись демонстрирует то, как на самом деле элементы массива размещаются в памяти компьютера. Как я уже писал в предыдущих главах, они идут последовательно.
Если инициализация двумерного массива происходит одновременно с объявлением, то можно даже не указывать первый индекс, т.е. количество строк массива.
1.int aMatrix[][5] = {{3, 5, 5, 7, 8},
2. {4, 1, 1, 2, 9},
3. {3, 8, 8, 9, 7}};
Зная количество столбцов, компилятор при компиляции сам рассчитает количество строк двумерного массива.
Для доступа к элементам двумерного массива нужно, так же, как и для одномерного указать индекс. В данном случае нам нужно будет позаботиться об указании двух индексов. Например, чтобы перезаписать последний элемент второй строки, мы должны использовать такую запись
1.aMatrix[1][4] = 0;
В этом случае мы перезапишем значение 9 на 0.
Для прохода по двумерному массиву удобнее всего использовать два цикла for, вложенных друг в друга. Ниже на примере мы выводим содержимое двумерного массива на экран.
01.//Работа с двумерным массиво
02.
03.#include <iostream>
04.
05.using namespace std;
06.
07.int main()
08.{
09. int aMatrix[3][5] = {{3, 5, 5, 7, 8},
10. {4, 1, 1, 2, 9},
11. {3, 8, 8, 9, 7}};
12.
13. aMatrix[1][4] = 0;
14.
15. for(int i = 0; i < 3; i++)
16. {
17. for(int j = 0; j < 5; j++)
18. {
19. cout << aMatrix[i][j] << ", ";
20. }
21.
22. cout << endl;
23. }
24.
25. return 0;
26.}
Результат работы программы:
Решение задач на двумерные массивы
Первая задача:
1. Нужно создать двумерный массив, размером 5 х 7 (пять строк, семь столбцов). Заполнить его случайно целыми числами, в районе от 0 до 30. Вывести получившийся массив на экран. Затем нужно отсортировать строки массива так, чтобы первой шла строка, сумма элементов которой была меньше, чем остальных. И так далее, по возрастанию. Для сортировки удобно использовать, алгоритм сортировки отбором. Вот только в этом случае этот алгоритм сортировки уже будет сортировать не отдельные числа одномерного массива, а строки двумерного массива, исходя из суммы ее элементов.
28. //делаем проходы столько раз, сколько строк в массиве
29. for(int N = 0; N < column - 1; N++)
30. {
31. result = row * 30;
32.
33. //анализируем массив и находим строку,
34. //сумма элементов которой минимальная
35. for(int i = N; i < column; i++)
36. {
37. //обнуляем счетчик суммы элементов строки
38. counter = 0;
39.
40. //проходим по элементам данной строки
41. //и считаем сумму
42. for(int j = 0; j < row; j++)
43. counter += matrix[i][j];
44.
45. //result в итоге будет хранить значение минимальной суммы
46. //columnMin будет хранить значение строки, в которой
47. //была найдена минимальная сумма
48. if(result > counter)
49. {
50. result = counter;
51. columnMin = i;
52. }
53. }
54.
55. replaceColumn(matrix, row, N, columnMin);
56. }
57.
58. //печатаем отсортированный массив
59. cout << "\nSorted array" << endl << endl;
60. printMatrix(matrix, column, row);
61.
62. return 0;
63.}
64.
65.//инициализация двумерного массива
66.void initMatrix(int matrix[][7], const int column, const int row)
67.{
68. for(int i = 0; i < column; i++)
69. for(int j = 0; j < row; j++)
70. matrix[i][j] = rand() % 30;
71.}
72.
73.//меняем строки массива местами
74.void replaceColumn(int matrix[][7], const int row, int N, int columnMin)
75.{
76. int buffer[row];
77.
78. for(int j = 0; j < row; j++)
79. {
80. buffer[j] = matrix[columnMin][j];
81. matrix[columnMin][j] = matrix[N][j];
82. matrix[N][j] = buffer[j];
83. }
84.}
85.
86.//печать двумерного массива
87.void printMatrix(int matrix[][7], const int column, const int row)
88.{
89. for(int i = 0; i < column; i++)
90. {
91. for(int j = 0; j < row; j++)
92. cout << setw(3) << matrix[i][j];
93.
94. cout << endl;
95. }
96.}
Результат работы программы:
Разработаем несложную программу, на обработку двумерного массива, которая называется «Лабиринт». Лабиринт должен быть построен на основе двумерного массива. Размер лабиринта выберем на свое усмотрение.
//#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{ // 1-условно "стенки лабиринта" // 2-"правильный путь, выход из лабиринта" // 0-"ложный путь"
int mas[33][20] = { {1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,}, // инициализация двумерного массива
{1,2,1,0,0,1,0,1,2,2,2,1,1,1,1,0,0,0,0,1,},
{1,2,1,1,0,1,0,1,2,1,2,2,2,2,1,0,1,1,0,1,},
{1,2,2,2,2,2,2,1,2,1,1,1,1,2,1,0,0,1,0,1,},
{1,1,1,1,1,1,2,1,2,1,0,0,1,2,1,1,0,1,0,1,},
{1,0,0,1,0,0,2,2,2,1,1,0,0,2,0,0,0,1,0,1,},
{1,0,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,1,0,1,},
{1,0,0,0,0,0,0,0,0,1,1,1,1,2,1,0,0,0,0,1,},
{1,1,1,1,1,1,0,1,1,1,2,2,2,2,1,0,1,1,1,1,},
{1,1,0,0,0,1,0,0,1,1,2,1,1,1,1,0,0,0,0,1,},
{1,0,0,1,0,0,0,0,0,1,2,2,2,2,1,1,1,1,0,1,},
{1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,0,0,0,1,},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,1,1,1,1,},
{1,2,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,},
{1,2,1,0,0,0,1,2,2,2,1,0,0,0,0,0,1,1,0,1,},
{1,2,1,1,1,1,1,2,1,2,1,1,1,0,1,0,0,0,0,1,},
{1,2,1,2,2,2,1,2,1,2,2,2,1,1,1,1,1,1,1,1,},
{1,2,1,2,1,2,1,2,1,0,1,2,2,2,2,2,2,2,2,1,},
{1,2,1,2,1,2,1,2,1,0,1,1,1,1,1,1,1,1,2,1,},
{1,2,1,2,1,2,1,2,1,0,0,0,0,0,0,0,0,0,2,1,},
{1,2,1,2,1,2,2,2,1,0,1,1,1,1,1,1,0,1,2,1,},
{1,2,1,2,1,1,1,1,1,0,0,0,1,0,1,0,0,1,2,1,},
{1,2,1,2,2,1,0,0,1,1,1,0,0,0,1,0,1,1,2,1,},
{1,2,1,1,2,1,1,0,0,0,0,0,1,0,1,0,0,1,2,1,},
{1,2,1,1,2,1,0,0,1,1,1,1,1,1,1,1,1,1,2,1,},
{1,2,1,1,2,1,1,0,1,2,2,2,2,2,2,2,2,2,2,1,},
{1,2,1,1,2,1,0,0,1,2,1,1,1,1,1,1,1,1,1,1,},
{1,2,1,1,2,1,0,1,1,2,1,1,1,1,1,1,1,1,2,2,},
{1,2,1,1,2,1,0,0,1,2,1,1,2,2,2,2,2,2,2,1,},
{1,2,1,1,2,1,0,1,1,2,1,1,2,1,1,1,1,1,1,1,},
{1,2,1,1,2,1,0,0,1,2,1,1,2,1,0,0,0,1,0,1,},
{1,2,2,2,2,1,0,1,1,2,2,2,2,0,0,1,0,0,0,1,},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,} }; // два цикла - внутренний и внешний, осуществляющие обращение к каждому элементу массива
for (int i = 0; i < 33; i++) //переключение по строкам
{
for (int j = 0; j < 20; j++)// переключение по столбцам
if (mas[i][j] == 1)
{
// вывести два раза символ (номер которого 176 в таблице аски) в консоль
cout << static_cast<char>(176);
cout << static_cast<char>(176);
}
else
cout << " "; // вывести два пробела
cout << endl;
}
system("pause");
return 0; }
Правильный и ложный пути можно было бы обозначать одной и той же цифрой, например, нулём, но для наглядности правильный путь обозначен цифрой 2. Инициализация массива выполнялась вручную, только для того, что бы упростить программу. Так как в программе выполняется обработка двумерного массива, нужны два цикла, для переключения между элементами двумерного массива. Первый цикл for выполняет переключение между строками двумерного массива. Так как строк в двумерном массиве 33, то и переменная-счетчик i инкрементируется от 0 до 33. Внутри первого цикла стоит цикл for, который переключается между элементами строки двумерного массива. В теле второго цикла for внутри оператора условного выбора if выполняетcя унарная операция преобразования типа данных - static_cast<>(), которая печатает символ таблицы ASCII, под номером 176. операция преобразования типов данных дублируется для увеличения ширины лабиринта. Результат работы программы.