Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Рацеев С.М. Программирование на языке Си.pdf
Скачиваний:
369
Добавлен:
23.03.2016
Размер:
1.65 Mб
Скачать

6.МНОГОМЕРНЫЕ МАССИВЫ

6.1.Определение и инициализация двумерных массивов

Вязыке Си имеется возможность создавать n-мерные массивы. Стандарт ANSI предусматривает, что значение n может быть по крайней мере любым числом в пределах от 1 до 12.

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

int a[10][20];

То есть тем самым определен двумерный массив целых чисел a, состоящий из 10 строк и 20 столбцов. Каждый элемент двумерного массива однозначно определяется парой индексов i и j: a[i][j], где i

– номер строки, а j – номер столбца. Как и в случае одномерных массивов, нумерация по переменным i и j начинается с нуля: a[0][0] – элемент, находящийся на пересечении нулевой строки и нулевого столбца… a[9][19] – элемент, находящийся на пересечении девятой строки и девятнадцатого столбца.

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

int a[3][2] = {{1, 2}, {3, 4}, {5, 6}};

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

int a[3][2] = {1, 2, 3, 4, 5, 6};

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

int a[3][2] = {{1}, {3}, {5}};

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

1

0

3

0

5

0

72

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

int a[10][20] = {0};

6.2. Примеры с двумерными массивами

Пример 1. Инициализация и вывод двумерного массива на экран.

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

#define M 5 /* Число строк матрицы */ #define N 10 /* Число столбцов матрицы */

/* заполнение матрицы случайными числами от 0 до 99 */ void Init(int a[][N], int m, int n)

{

int i, j;

for (i = 0; i < m; i++) for (j = 0; j < n; j++)

a[i][j] = rand()%100;

}

/* вывод матрицы на экран */ void Print(int a[][N], int m, int n)

{

int i, j;

for (i = 0; i < m; i++)

{

for (j = 0; j < n; j++) printf("%5d", a[i][j]);

printf("\n");

}

}

73

int main()

 

{

 

int a[M][N];

/* матрица размера M на N */

srand(time(NULL));

Init(a, M, N);

/* инициализация элементов матрицы */

Print(a, M, N);

/* вывод матрицы на экран */

return 0;

 

}

 

При этом заметим очень важный момент. Массив int a[M][N] является одномерным массивом размера M, каждый элемент которого является целочисленным массивом размерности N, то есть каждый из M элементов массива a имеет тип int a[N]. В соответствии с данной логикой элемент a[0] является одномерным массивом, представляющим первую строку матрицы a. Поэтому a[i] – одномерный массив, представляющий i-ую строку матрицы a.

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

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

#include<stdio.h>

#include<stdlib.h>

#define M 5 /* Число строк матрицы */ #define N 10 /* Число столбцов матрицы */

/* заполнение одномерного массива a случайными числами */ void Init(int *a, int n)

{

int i;

for (i = 0; i < n; i++) a[i] = rand()%100;

}

74

/* вывод одномерного массива a на экран */ void Print(int *a, int n)

{

int i;

for(i = 0; i < n; i++) printf("%5d", a[i]);

putchar('\n');

}

int main()

{

int i, a[M][N]; /* матрица размера M на N */

/* инициализация каждой строки матрицы: */ for (i = 0; i < M; i++)

Init(a[i], N);

/* вывод элементов матрицы построчно: */ for (i = 0; i < M; i++)

Print(a[i], N); return 0;

}

Пример 2. Пусть имеется двумерный массив int a[M][N] и одномерный массив int b[MN]. Требуется элементы массива b построчно записать в матрицу a.

Для решения данной задачи учтем важное замечание из предыдущего примера. Если представить двумерный массив a[M][N] в виде последовательно расположенных одномерных массивом размера N, то k-ый элемент (0 ≤ k MN-1) полученного ‘большого’ одномерного массива соответствует a[k/N][k%N] элементу матрицы, что следует из однозначного разложения числа k по модулю числа N:

k = i*N + j, 0 ≤ j < N.

Поэтому решить задачу можно с помощью такого алгоритма: int k;

for(k = 0; k < M*N; k++) a[k/N][k%N] = b[k];

75

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

for(k = 0; k < M*N; k++) *(*a + k) = b[k];

где *a – адрес первого элемента матрицы a, *a + k – адрес k-го элемента матрицы, *(*a + k) – значение k-го элемента.

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

for (i = 0; i < M; i++) for(j = 0; j < N; j++)

b[i*N + j] = a[i][j];

Если учесть замечание, связанное с эффективностью использования адресной арифметики, то данный алгоритм можно записать в такой форме:

for(k = 0; k < M*N; k++) b[k] = *(*a + k);

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

#include<stdio.h>

#include<stdlib.h> #define M 5 #define N 10

/* проверка одномерного массива на упорядоченность */ int IsSort(int *a, int n)

{

int i;

for(i = 0; i < n && a[i-1] <= a[i]; i++)

;

return (i >= n);

}

76

int main()

{

int a[M][N], i, count;

Init(a, M, N); /* функция из первого примера */ for(i = count = 0; i < M; i++)

if (IsSort(a[i], N)) count++;

printf("count = %d\n", count); return 0;

}

Пример 4. Пусть имеется некоторая квадратная матрица a размера n. Требуется вывести на экран все подматрицы данной матрицы порядка 1, 2,…,n.

#include<stdio.h> #define N 5

/* вывод подматрицы порядка size, левая верхняя вершина которой имеет координаты (i0, j0) в матрице a:

*/

void Print(int a[][N], int i0, int j0, int size)

{

int i, j;

for (i = i0; i < i0 + size; i++)

{

for (j = j0; j < j0 + size; j++) printf("%5d", a[i][j]);

printf("\n");

}

printf("\n");

}

/* функция рассматривает все подматрицы в матрице a */ void SubMatrix(int a[][N], int n)

{

77