
- •Содержание
- •Лабораторная работа №9 классы хранения и видимость переменных
- •Теоретические сведения
- •Варианты индивидуальных заданий
- •Приложение 1
- •Лабораторная работа №10 препроцессорные средства
- •Теоретические сведения
- •1. Состав директив препроцессора и стадии препроцессорной обработки
- •2. Стадии препроцессорной обработки
- •3. Замены в тексте программы
- •4. Цепочка подстановок
- •5. Включение текстов из файлов
- •6. Условная компиляция
- •7. Операция defined
- •8. Макроподстановки средствами препроцессора
- •9. Моделирование многомерных массивов
- •10. Отличия макросов от функций
- •11. Препроцессорные операции в строке замещения
- •12. Вспомогательные директивы
- •13. Реакция на ошибки
- •14. Пустая директива
- •15. Встроенные (заранее определенные) макроимена
- •Варианты индивидуальных заданий
- •Лабораторная работа № 11 динамическое распределение памяти
- •Теоретические сведения
- •1. Функции malloc и free
- •2. Операторы new и delete
- •Варианты индивидуальных заданий
- •Лабораторная работа № 12 структура данных «список»
- •Теоретические сведения
- •1. Основные определения
- •2. Операции над списками
- •3. Пример реализации односвязного списка с помощью массива структур
- •4. Пример реализации двусвязного списка с помощью массива данных
- •Варианты индивидуальных заданий
- •Лабораторная работа №13 очереди. Операции над очередями. Деки
- •Теоретические сведения
- •1. Понятие очереди. Операции над очередями. Кольцевая очередь. Дек
- •2. Программная реализация очереди на основе массива
- •Варианты индивидуальных заданий
- •Лабораторная работа №14 стеки. Очереди. Операции над стеками и очередями
- •Теоретические сведения
- •1. Понятие стека. Операции над стеком
- •2. Программная реализация стека на основе массива
- •Варианты индивидуальных заданий
- •Лабораторная работа №15
- •Анализ пузырьковой сортировки. Пузырьковая сортировка обладает несколькими характеристиками:
- •2. Сортировка методом выбора
- •3. Сортировка методом вставки
- •4. Сортировка методом Шелла
- •5. Сортировка методом Хоора
- •6. Алгоритмы поиска
- •Варианты индивидуальных заданий
- •Приложение 2
- •Лабораторная работа №16 программирование алгоритмов вычислительной математики
- •Теоретические сведения
- •1. Методы Симпсона
- •Варианты индивидуальных заданий
- •Литература
9. Моделирование многомерных массивов
Основным понятием в языке Си является одномерный массив, а возможности формирования многомерных массивов (особенно с переменными размерами) весьма ограничены. Напомним, что нумерация элементов массивов в языке Си начинается с нуля, т.е. для обращения к начальному (первому) элементу массива требуется нулевое значение индекса.
При работе с матрицами обе указанные особенности массивов языка Си создают по крайней мере неудобства. Во-первых, при обращении к элементу матрицы нужно указывать два индекса – номер строки и номер столбца элемента матрицы. Во-вторых, нумерацию строк и столбцов матрицы принято начинать с 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));
}}
-
Строка 1
0.0
1.0
2.0
3.0
4.0
Строка 2
5.0
6.0
7.0
8.0
9.0
Строка 3
10.0
11.0
12.0
13.0
14.0
Строка 4
15.0
16.0
17.0
18.0
19.0
Рис. 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]:
0 |
1 |
2 |
3 |
4 |
5 |
… |
16 |
17 |
18 |
19 |
0.0 |
1.0 |
2.0 |
3.0 |
4.0 |
5.0 |
…. |
16.0 |
17.0 |
18.0 |
19.0 |
М=5 |
…. |
М=5 | ||||||||
|
|
|
|
|
|
|
|
|
|
j-й столбец
|
|
|
|
|
|
|
|
0.0 |
1.0 |
2.0 |
3.0 |
4.0 |
Матрица А |
i-я строкастрока |
5.0 |
6.0 |
7.0 |
8.0 |
9.0 |
С |
|
10.0 |
11.0 |
12.0 |
13.0 |
14.0 |
Размерами |
| ||||||
|
15.0 |
16.0 |
17.0 |
18.0 |
19.0 |
4x5 |
А (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. Имитация матрицы с помощью макроопределения и одномерного массива