Как инициализировать двумерный массив c
Перейти к содержимому

Как инициализировать двумерный массив c

  • автор:

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

С позволяет создавать многомерные массивы. Простейшим видом многомерного массива является двумерный массив. Двумерный массив — это массив одномерных массивов. Двумерный массив объявляется следующим образом:

тип имя_массива[размер второго измерения][размер первого измерения];

Следовательно, для объявления двумерного массива целых с размером 10 на 20 следует написать:

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

Для доступа к элементу с индексами 3, 5 массива d следует использовать

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

#include
int main(void)
int t,i, num[3][4];
/* загрузка чисел */
for(t=0; t for (i=0; i num[t][i] = (t*4)+i+1;

В данном примере num[0][0] имеет значение 1, num[0][1] имеет значение 2, num[0][2] — 3 и так далее. num[2][3] имеет значение 12.

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

Число байт в памяти, требуемых для размещения двумерного массива, вычисляется следующим образом:

число байт = размер второго измерения * размер первого измерения * sizeof (базовый тип)

Предполагая наличие в системе 2-байтных целых, целочисленный массив с размерностями 10 на 5 будет занимать 10 * 5 * 2, то есть 100 байт.

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

Можно определить размер второго измерения, но это не обязательно. Компилятору нужно знать размер первого измерения для правильного выполнения операторов типа

в функции. Если длина строки не известна, невозможно узнать, где начинается следующая строка.

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

#include
#include
#include
#include
#define CLASSES 3
#define GRADES 30
int grade[CLASSES][GRADES];
void disp_grades(int g[] [GRADES]), enter_grades(void);
int get_grade(int num);
int main(void) /* программа для хранения оценок */
char ch;
for (;;) do printf(«(E)nter grades\n»);
printf(«(R)eport grades\n»);
printf(«(Q) uit\n»);
ch = toupper(getche());
>
while(ch!=’E’ && ch!=’R’ && ch!=’Q’);
switch(ch)
case ‘E’:
enter_grades();
break;
case ‘R’:
disp_grades(grade);
break;
case ‘Q’:
return 0;
>
>
>

/* ввод каждой оценки студентов */
void enter_grades(void)
int t, i;
for(t=0; t for(i=0; i grade[t][i] = get_grade (i);
>
>

/* реальный ввод оценки */
int get_grade(int num) char s [80];
printf(«enter grade for student # %d:\n», num+1);
gets (s);
return(atoi(s));
>

/* вывод оценок класса */
void disp_grades(int g[] [GRADES])
int t, i;
for(t=0; t printf(«Class # %d:\n», t+1);
for(i=0; i printf(«grade for student #%d is %d\n», i+1, g[t][i]);
>
>

Рисунок. Размещение двумерного массива в памяти

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

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

спецификатор типа имя_массива [размерN] . [размер1] = ;

Список значений — это разделенный запятыми список констант, совместимых по типу со спецификатором типа. Первая константа помещается в первый элемент массива, вторая — во второй и так далее. За последней константой списка нет запятой. Обратим внимание, что точка с запятой следует за >. В следующем примере 10-элементный целочисленный массив инициализируется числами от 1 до 10:

Это означает, что i[0] получит значение 1, i[9] — 10.

Массивы символов, содержащие строки, допускают удобную инициализацию в виде

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

При данной инициализации нулевой терминатор автоматически добавляется к концу строки. Нижеприведенный фрагмент кода инициализирует строку str фразой «hello»:

char str[6] = «hello»;

Это можно также записать:

Обратим внимание, что в данной версии следует явным образом указать нулевой символ. Поскольку все строки в С оканчиваются нулевым символом, следует убедиться, что массив достаточно длинный для его вмещения. Именно поэтому str состоит из 6 символов, хотя «hello» имеет только 5 символов.

Многомерные массивы инициализируются так же, как и одномерные. Следующий пример инициализирует sqrs числами от 1 до 10 и их квадратами:

Здесь sqrs[0][0] содержит 1, sqrs[0][1] содержит 1, sqrs[1][0] содержит 2, sqrs[1][1] содержит 4 и так далее.

При инициализации многомерных массивов можно добавить фигурные скобки вокруг каждого измерения. Это так называемая субагрегатная группировка. Ниже приведен еще один способ записи предыдущего объявления:

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

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

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

 [размерность1][размерность2]. ;

Например, двумерный массив

int a[2][3];
int a[3][4][5];

Доступ до элементов массива осуществляется также, как и в одномерном массиве

#include #include #define SIZE 5 void main() < int M[3][3]; unsigned i, j; for (i = 0; i < 3; i++) < for (j = 0; j < 3; j++) < M[i][j] = i * j; >> do < printf("enter indexes:\n"); scanf("%d", &i); scanf("%d", &j); if (i < 3 && j < 3) < printf("M[%d][%d] == %d\n", i, j, M[i][j]); >else < break; >> while (1); for (i = 0; i < 3; i++) < for (j = 0; j < 3; j++) < printf("\t%d", M[i][j]); >printf("\n"); > getch(); >

Особенностью является то, что по своему строению многомерный массив является обыкновенным, «одномерным», массивом. Все элементы расположены друг за другом. Доступ до элемента a[i][j] – по существу сдвиг на i*число столбцов + j. В двумерном массиве, таким образом, элементы расположены «по рядам», в трёхмерном — «по слоям», внутри которых элементы расположены «по рядам» и т.д.
В связи с этим, при начальной инициализации опускать размерность можно только в первых квадратных скобках:

int a[][3] = ; int b[][5][25] = ;

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

int a[2][3] = ;

Можно опустить первую размерность

int a[][2][3] = ;

Можно с помощью фигурных скобок сделать данные более удобными для чтения

int a[2][3] = {{1, 2, 3>, 
int a[][3][4] = {{{1, 2, 3, 4>, , , , , , 

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

int zero3[3][3] = {{1>, , 

Из того, что многомерный массив является одномерным по структуре, вытекают некоторые интересные свойства. Например, доступ до элемента может быть осуществлён через его порядковый номер
a[i][j] === a[0][i*число столбцов + j] и т.д.

Примеры

1. Отсортируем двумерный массив методом пузырька. Для сортировки обычно используется два подхода - превращение двумерного массива в одномерный, сортировка, обратно превращение одномерного в двумерный, либо запутанное обращение к элементам через индекс. Можно сделать всё проще: работать с многомерным массивом как с одномерным

#include #include #define ROWS 4 #define COLS 3 void main() < int a[ROWS][COLS] = {{1, 4, 5>, , , > > while(flag); for (i = 0; i < ROWS; i++) < for (j = 0; j < COLS; j++) < printf("%3d", a[i][j]); >printf("\n"); > _getch(); >

Замечание: по стандарту явно такое поведение не определено, но косвенно должно поддерживаться.

2. Даны координаты x и y точки, полученные в ходе фотосъёмки. Известно, сколько кадров в секунду делала камера. Вычислить скорость в каждый момент времени и среднюю скорость за всё время.

#include #include #include #define SIZE 10 void main() < float a[2][SIZE] = {{1.03, 1.52, 2.11, 2.53, 3.08, 3.48, 3.98, 4.51, 5.02, 5.17>, speed /= (float)(SIZE - 1); for (i = 1; i < SIZE; i++) < printf("v[%d] = %.3f m/s\n", i, velocity[i-1]); >printf("mean velocity = %.3f", speed); _getch(); >

3. Массив используется как карта, где число 2 означает начало, а 3 - конец пути. Программа сначала находит координаты этих точек, после этого вычисляет расстояние Манхеттена (сколько нужно пройти по x и y от начала до конца) и расстояние по Евклиду (как гипотенузу прямоугольного треугольника).

#include #include #include #define SIZE 5 #define START 2 #define FINISH 3 void main() < char field[SIZE][SIZE] = < , , , , >; unsigned i, j; unsigned x, y; char xFound = 0; int X, Y; char XFound = 0; unsigned manhattanDist; float euclidDist; for (i = 0; i < SIZE; i++) < for (j = 0; j < SIZE; j++) < if (field[i][j] == START) < x = i; y = j; xFound = 1; if (XFound) < break; >> if (field[i][j] == FINISH) < X = i; Y = j; XFound = 1; if (xFound) < break; >> > if (xFound && XFound) < break; >> if (!(xFound && XFound)) < printf("Error: corrupted data\n"); getch(); exit(1); >printf("(x,y) = %d, %d\n(X,Y)= %d, %d\n", x, y, X, Y); manhattanDist = abs((int)(x-X)) + abs((int)(y-Y)); //тоже самое, что и sqrt((x-X)*(x-X)+(y-Y)*(y-Y)) x -= X; y -= Y; euclidDist = sqrt((float)(x*x + y*y)); printf("Manhattan dist. = %d\nEuclid dist. = %.3f", manhattanDist, euclidDist); getch(); >

4. Пользователь вводит 10 слов. Вывести слово с максимальной длиной. Программа внешне совершенно простая, единственная проблема - считывание и вывод слова. Так как слова храняться в двумерном массиве, то указатель на words[i][0] - это начало нового слова. Также не забываем об ограничении на длину при вводе.

#include #include #define SIZE 10 #define MAX_LENGTH 128 void main() < //Массив хранит 10 слов максимум по 128 символов char words[SIZE][MAX_LENGTH]; unsigned i, j, maxLength; //Так как длина слова ограничена 127 символами, то типа char хватит unsigned char counter[SIZE]; for (i = 0; i < SIZE; i++) < //Считываем слова. words[i][0] - это символ, нам нужен //адрес, начиная с которого можно писать в массив fgets(&words[i][0], MAX_LENGTH - 1, stdin); j = 0; //Считаем длину слова while (words[i][j]) < j++; >counter[i] = j; > //Ищем слово с максимальной длиной maxLength = counter[0]; j = 0; for (i = 1; i < SIZE; i++) < if (counter[i] >maxLength) < maxLength = counter[i]; j = i; >> //Выводим слово на печать. При выводе строки //необходимо передавать указатель printf("%s", &words[j][0]); _getch(); >

ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 sypachev_s_s@mail.ru Stepan Sypachev students

email

Всё ещё не понятно? – пиши вопросы на ящик

Как инициализировать двумерный массив в классе? [закрыт]

Вопросы с просьбами помочь с отладкой («почему этот код не работает?») должны включать желаемое поведение, конкретную проблему или ошибку и минимальный код для её воспроизведения прямо в вопросе. Вопросы без явного описания проблемы бесполезны для остальных посетителей. См. Как создать минимальный, самодостаточный и воспроизводимый пример.

Закрыт 7 лет назад .

#include #include using namespace std; const int n = 8; int dx[] = ; int dy[] = ; class HorseMove < public: int **Solution = new int *[n]; for (int i = 0; i < n; i++)< Solution[i] = new int *[n]; >bool Success = false; int Step(int i, int x, int y) < if (Success) < return 1; >if ((x < 0) || (x >= n) || (y < 0) || (y >= n) || (Solution[x][y] > 0)) < return 1; >Solution[x][y] = i; if (i = n * n) < Success = true; >else < for(int k = 0; k > if (!Success) < Solution[x][y] = 0; >> >; const int x0 = 1, y0 = 3; int main(void) < setlocale(LC_ALL, "Russian"); HorseMove Chess; Chess.Step(1, x0, y0); if (Chess.Success) < cout return 0; > 

Отслеживать
222k 15 15 золотых знаков 120 120 серебряных знаков 234 234 бронзовых знака
задан 23 апр 2017 в 13:32

Это у вас точно такой код? Сразу после public: не объявление члена, а голый код. И - все же поясните, что вы хотите сделать, из вашего кода непонятно, где именно проблемы.

23 апр 2017 в 13:34

Дружище, прочти какую-нибудь хорошую книгу для начинающих, а то твой код очень уж странный. Начни с того, что не используй C-style двумерные массивы, сырые указатели, глобальные переменные и константы, не пиши названия переменных с больших букв (ни в CamelCase, ни в stl_case так не делается), приучи себя по возможности не использовать using namespace std , а везде приписывать std:: при указании функций, например ( std::cout ), в будущем тебе это пригодится. И да, почитай, что такое классы и зачем они нужны.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *