Моделирование многомерных массивов
Основным понятием в языке Си является одномерный массив, а возможности формирования многомерных массивов (особенно с переменными размерами) весьма ограничены. Напомним, что нумерация элементов массивов в языке Си начинается с нуля, т.е. для обращения к начальному (первому) элементу массива требуется нулевое значение индекса. При работе с матрицами обе указанные особенности массивов языка Си создают по крайней мере неудобства. Во-первых, при обращении к элементу матрицы нужно указывать два индекса – номер строки и номер столбца элемента матрицы. Во-вторых, нумерацию строк и столбцов матрицы принято начинать с 1. Применение макросов для организации доступа к элементам массива позволяет программисту обойти оба указанных затруднения, правда, за счет нетрадиционных обозначений индексированных элементов (индексы в макросах, представляющих элементы массивов матриц, заключены в круглые, а не в квадратные скобки).
Рассмотрим следующую программу: Пример 10.17 #define N 4 /* Число строк матрицы */ #define M 5 /* Число столбцов матрицы */ #define A(i, j) x[M*(i-l) + (j-1)] #include < stdio.h> void main () { /* Определение одномерного массива */ double x[N*M]; int i, j, k; for (k = 0; k < N*M; k++) x[k]=k; for (i = l; i < = N; i++) /* Перебор строк */ { printf (“\n Строка %d: ”, i); /* Перебор элементов строки */ for (j = l; j < = M; j++) printf< ” %6.1f”, A(i, j)); }}
Рис. 10.2. Результат выполнения программы
В программе определен одномерный массив х[ ], количество элементов в котором зависит от значений препроцессорных идентификаторов N и М. Значения элементам массива х[ ] присваиваются в цикле с параметром k. Далее для доступа к элементам того же массива х[ ] используются макровызовы вида A(i, j), причем i изменяется от 1 до N, а переменная j изменяется во внутреннем цикле от 1 до М. Переменная i соответствует номеру строки матрицы, а переменная j играет роль второго индекса, т.е. указывает номер столбца. При таком подходе программист оперирует с достаточно естественными обозначениями A(i, j) элементов матрицы, причем нумерация столбцов и строк начинается с 1, как и предполагается в матричном исчислении. В тексте программы за счет макрорасширений в процессе препроцессорной обработки выполняются замены параметризованных обозначений A(i, j) на x[5*(i-l)+(j-1)], и далее действия выполняются над элементами одномерного массива х[ ]. Но этих преобразований не видно и можно считать, что идет работа с традиционными обозначениями матричных элементов. Использованный в программе оператор (вызов функции) printf (“% 6.lf”, A (i, j)); после макроподстановок будет иметь вид printf (“% 6.lf”, x[5*(i-l) + (j-l)]);
На рис. 10.3 приведена иллюстративная схема одномерного массива х[ ] и виртуальной (существующей только в воображении программиста, использующего макроопределения) матрицы для рассмотренной программы. Одномерный массив х[20]:
j-й столбец
А (1, 1) соответствует х[5*(1-1)+(1-1)] = = х[0] А (1, 2) соответствует х[5*(1-1)+(2-1)] = = х[1] А (2, 1) соответствует х[5*(2-1)+(1-1)] = = х[5] А (3, 4) соответствует х[5*(3-1)+(4-1)] = = х[13] Рис. 10.3. Имитация матрицы с помощью макроопределения и одномерного массива
|