Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3 Функции и структуры программ.docx
Скачиваний:
4
Добавлен:
01.07.2025
Размер:
33 Кб
Скачать
☆

30. Рекурсия.

Проблему можно решить двумя способами. Первый - запомнить цифры в некотором массиве в том порядке, как они получались, а затем напечатать их в обратном порядке; так это и было сделано в функции itoa, рассмотренной в параграфе 3.6. Второй способ - воспользоваться рекурсией, при которой printd сначала вызывает себя, чтобы напечатать все старшие цифры, и затем печатает последнюю младшую цифру. Эта программа, как и предыдущий ее вариант, при использовании самого большого по модулю отрицательного числа работает неправильно.

#include <stdio.h>

/* printd: печатает n как целое десятичное число */

void printd(int n)

{

if (n < 0) {

putchar('-');

n = -n;

}

if (n / 10)

printd(n / 10);

putchar(n % 10 + '0');

}

Когда функция рекурсивно обращается сама к себе, каждое следующее обращение сопровождается получением ею нового полного набора автоматических переменных, независимых от предыдущих наборов. Так, в обращении printd(123) при первом вызове аргумент n = 123, при втором - printd получает аргумент 12, при третьем вызове - значение 1. Функция printd на третьем уровне вызова печатает 1 и возвращается на второй уровень, после чего печатает цифру 2 и возвращается на первый уровень. Здесь она печатает 3 и заканчивает работу.

31. Включение файла.

Средство #include позволяет, в частности, легко манипулировать наборами #define и объявлений. Любая строка вида:

#include "имя-файла"

или

#include <имя-файла>

заменяется содержимым файла с именем имя-файла. Если имя-файла заключено в двойные кавычки, то, как правило, файл ищется среди исходных файлов программы; если такового не оказалось или имя файла заключено в угловые скобки < и >, то поиск осуществляется по определенным в реализации правилам. Включаемый файл сам может содержать в себе строки #include.

Директива #include — это оптимальный способ собрать все объявления в нужном месте в большой программе. Этот способ гарантирует, что все файлы исходного кода будут включать одни и те же макроопределения и объявления внешних переменных, таким образом ликвидируя возможность появления особенно неприятных

32. Макроподстановки.

#define имя текст для замены

Это — макроопределение простейшего вида; всякий раз, когда имя встретится в тексте программы после этого определения, оно будет заменено на текст-для-замены.

Например, таким образом можно определить имя forever, обозначающее бесконечный цикл:

#define forever for (;;) /* бесконечный цикл */

Например, так определяется макрос с именем max:

#define max(А, В) ((А) > (В) ? (А) : (В))

Хотя внешне он напоминает вызов функции, на самом деле max разворачивается прямо в тексте программы путем подстановки. Вместо формальных параметров (А или В) будут подставлены фактические аргументы, обнаруженные в тексте. Возьмем, например, следующий макровызов:

х = max(p+q, r+s);

33. Условное включение.

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

Вычисляется константное целое выражение, заданное в строке #if. Это выражение не должно содержать ни одного оператора sizeof или приведения к типу и ни одной enum-константы. Если оно имеет ненулевое значение, то будут включены все последующие строки вплоть до #endif, или #elif, или #else. (Инструкция препроцессора #elif похожа на else if.) Выражение defined(имя) в #if есть 1, если имя было определено, и 0 в противном случае.

Вот пример цепочки проверок имени SYSTEM, позволяющей выбрать нужный файл для включения:

#if SYSTEM == SYSV

#define HDR "sysv.h"

#elif SYSTEM == BSD

#define HDR "bsd.h"

#elif SYSTEM == MSDOS

#define HDR "msdos.h"

#else

#define HDR "default.h"

#endif

#include HDR