- •Списки §1. Общие сведения о списках
- •§2. Создание списка
- •§3. Просмотр и анализ списка
- •3.1. Просмотр и анализ списка целых чисел.
- •3.2. Просмотр и анализ списка одномерных массивов.
- •§6. Сравнительный анализ списков.
- •§1. Порядок работы с файлом
- •1.1. Потоки и файлы
- •1.2. Объявление файла
- •1.3. Открытие файла.
- •1.4. Закрытие файла.
- •§2. Работа с текстовым файлом
- •2.1. Посимвольная работа с текстовым файлом
- •Int fputc(int ch, file *stream)
- •2.2. Построчная работа с текстовым файлом
- •§3. Функции блокового ввода/вывода
- •3.1. Экономические задачи с использованием файлов
- •3.2. Математические задачи с использованием файлов
- •§4. Прямой (произвольный) доступ к файлу
- •4.1. Функция fseek()
- •4.2. Замена записи. Функции ftell, fgetpos, fsetpos, rewind.
- •Пример. В файл записать координаты точек плоскости. Найти две (любые) точки с наибольшим расстоянием между ними. Массив для хранения координат всех точек не использовать.
- •Упражнения, тесты.
- •Функции (дополнительные возможности)
- •§1. Функции с переменным количеством параметров.
- •§2. Указатели на функции.
- •§3. Массив указателей на функции.
- •§4. Введение в рекурсивные функции.
- •Упражнения, тесты.
- •Void Fun1 (float); void Fun2(float); void Fun3(float);
- •Лабораторная работа № 12.
- •Команды препроцессора (директивы компиляции)
- •§1. Директива define (замены в тексте)
- •Простое макроопределение (макрос)
- •Макрос с аргументами.
- •Директива #undef.
- •§2. Директива #include (включение файлов).
- •§3. Директивы условной компиляции.
- •Директива #if.
- •Директивы #ifdef и #ifndef.
- •Упражнения, тесты
- •История развития технологий программирования
- •§1. Программирование в машинных кодах и на языках символического кодирования
- •§2. Языки высокого уровня. Структурное и модульное программирование
- •§3. Интегрированные системы программирования.
- •§4. История и идеи объектно-ориентированного программирования.
- •§5. Программирование для Windows. Визуальное программирование.
- •Литература
- •Оглавление Предисловие………………………………………………………….…………………3
- •Г л а в а 4. Структуры и другие типы, определяемые пользователем.84
- •Г л а в а 6. Файлы ………………………………………………………..154
- •Г л а в а 7. Функции (дополнительные возможности) ………………190
- •Г л а в а 9. История развития технологий программирования ……220
Макрос с аргументами.
Директива #define имеет ещё одну интересную возможность: макрос может иметь аргументы, и тогда его называют макрос типа функции или макрос (макроопределение) с аргументами.
Пример 1. Можно определить следующий простой макрос
#define ZIKL1 for (int k=0; k<n; k++)
Но тогда макрос ZIKL1 заменится на оператор цикла, в котором его параметром является обязательно переменная k, которая меняется так, как указано в макроопределении, то есть только от 0 до n-1. Как расширить возможности такого макроса?
Будем использовать макроопределение с аргументами, общий вид которого следующий:
#define имя(арг1, арг2, …, аргN) последовательность_символов
Для нашего примера определим следующее макроопределение:
#define ZIKL2 (var, from, to) for (int var=from; var<to; var++)
C его помощью мы имеем возможность записывать различные заголовки цикла, меняя идентификатор для параметра цикла, его начальное и конечное значения при постоянном шаге изменения, равным +1. Если в тексте программы встретится макроопределение с фактическими параметрами k, 0 и n, то есть
ZIKL2 (k, 0, n),
то, как и в функции, k формально подставляется вместо var, 0 вместо from и n вместо to. В результате будет сформирован следующий заголовок цикла:
for (int k=0; k<n; k++).
Если бы надо было менять и шаг изменения параметра, то его можно было бы включить в качестве четвёртого параметра макроса с аргументами.
Пример 2. Определим следующий макрос с аргументами
#define MYPRINT (var) printf(#var); \
printf (“=%d\n”, var);
Если перед аргументом в макроопределении стоит знак “#”, то имя фактического параметра будет заключено в двойные кавычки. Тогда вместо, например,
MYPRINT (b)
будет компилироваться следующая строка, полученная в результате макроподстановки:
printf(“b”); printf (“=%d\n”, b);
При этом вместо var будет подставлено b.
Пример 3. Оператор препроцессора ## используется для соединения двух частей.
#define concat(u, v) u ## v
int xy =100;
printf(“%d”, concat(x,y));
Последнюю функцию вывода printf препроцессор преобразует в
printf(“%d”, xy);
и при выполнении будет выведено число 100.
Пример 4. Пусть определён макрос с аргументом для проверки, является ли число v чётным:
#define EVEN(v) v%2==0 ? 1 : 0
Если далее в программе будет записано
r=EVEN(9);
то такой оператор будет работать правильно. Он преобразуется следующим образом:
r=9%2==0 ? 1 : 0;
и проверит на чётность число 9.
Но несмотря на то, что макрос с аргументами чем то похож на функцию, имеется существенное отличие. Продолжим рассмотрение этого примера. Пусть k объявлено и определено как целое число. Тогда если запишем
r=EVEN (k+1);
то будет выполнена следующая подстановка
r=k+1%2==0 ? 1 : 0;
Сначала выполнится целочисленное деление, а затем его результат прибавится к переменной k. То есть макроподстановка выполнится не так, как если бы вместо макроса была бы определена функция, то есть неправильно. Нам надо было, чтобы после препроцессорной обработки получилось
r=(k+1)%2==0 ? 1 : 0;
Для этого при определении макроса параметр v необходимо заключить в круглые скобки:
#define EVEN(v) (v)%2==0 ? 1 : 0
В тексте программы при использовании такого макроса ничего не меняем:
r=EVEN (k+1);
Использование макроопределений с параметрами вместо функций существенно увеличивает скорость работы программы, так как не надо тратить время на вызов функции и возврат из неё. Но за данное увеличение скорости работы следует платить увеличением размера исполнимого кода программы, так как код макроса дублируется столько раз, сколько раз он записан в программе.