Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
projekt_ukr2.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
180.22 Кб
Скачать

Препроцесор. Рекурсія.

В мові Cі функції можуть використовуватися рекурсивно; це означає, що функція може прямо чи побічно звертатися до себе самої. Традиційним прикладом є друк числа у виді рядка символів, як ми вже раніше відзначали, цифри генеруються не в тім порядку: цифри молодших розрядів з'являються раніш цифр зі старших розрядів, але друкуватися вони повинні в зворотному порядку.

Цю проблему можна вирішити двома способами. Перший спосіб полягає в запам'ятовуванні цифр у деякому масиві в міру їхнього надходження і наступному їхньому друкуванні в зворотному порядку.

Альтернативою цьому способу є рекурсивне рішення, коли при кожному виклику функція PRINTF спочатку знову звертається до себе, щоб скопіювати лідируючі цифри, а потім друкує останню цифру.

Коли функція викликає себе рекурсивно, при кожнім звертанні утвориться новий набір всіх автоматичних змінних, що зовсім не залежить від попереднього набору. Таким чином, у PRINTF(123) перша функція PRINTF має N = 123. Вона передає 12 другій PRINTF, а коли та повертає керування їй, друкує 3. Точно так само друга PRINTF передає 1 третьої (яка цю одиницю друкує), а потім друкує 2.

Рекурсія звичайно не дає ніякий економії пам'яті, оскільки приходиться десь створювати стек для оброблюваних значень. Не призводить вона і до створення більш швидких програм. Але рекурсивні програми більш компактні, і вони найчастіше стають більш легкими для розуміння і написання. Рекурсія особливо зручна при роботі з рекурсивно обумовленими структурами даними.

У мові Сі передбачені визначення розширення мови за допомогою простого макропередпроцесору. Одним з найпоширеніших таких розширень, що ми уже використовували, є конструкція #DEFINE; іншим розширенням є можливість включати під час компіляції вміст інших файлів.

Для полегшення роботи з наборами конструкцій #DEFINE і описів (серед інших засобів) у мові Сі передбачена можливість включення файлів. Будь-який рядок виду

#INCLUDE "FILENAME" заміняється вмістом файлу з ім'ям FILENAME. (Лапки обов'язкові). Часто один чи два рядки такого виду з'являються на початку кожного вихідного файлу, для того щоб включити загальні конструкції #DEFINE і опису EXTERN для глобальних змінних. Допускається вкладеність конструкцій #INCLUDE.

Визначення виду #DEFINE TES 1 призводить до макропідстановки найпростішого виду – заміні імені на рядок символів. Імена в #DEFINE мають ту ж саму форму, що й ідентифікатори в Сі; текст, що заміняє довільний. "Область дії" імені, визначеного в #DEFINE, простирається від крапки визначення до кінця вихідного файлу. Імена можуть бути перевизначені, і визначення можуть використовувати визначення, зроблені раніше.

Лекція 8

Структури. Масив структур.

Структура - це набір з однієї чи більш змінних, можливо різних типів, згрупованих під одним ім'ям для зручності обробки. (У деяких мовах, найвідоміший з яких Паскаль, структури називаються "записами").

Традиційним прикладом структури є облікова картка працюючого: "службовець" описується набором атрибутів таких, як прізвище, ім'я, по батькові (п.і.б.), адреса, код соціального забезпечення, зарплата і т.д. Деякі з цих атрибутів самі можуть виявитися структурами: п.і.б.

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

Структури особливо підходять для керування масивами зв'язаних змінних. Розглянемо, наприклад, програму підрахунку числа входжень кожного ключового слова мови "C". Нам потрібний масив символьних рядків для збереження імен і масив цілих для підрахунку, одна з можливостей складається у використанні двох рівнобіжних масивів KEYWORD і KEYCOUNT:

CHAR *KEYWORD [NKEYS];

INT KEYCOUNT [NKEYS];

Але сам факт, що масиви рівнобіжні, вказує на можливість іншої організації. Кожне ключове слово тут власне кажучи є парою:

CHAR *KEYWORD;

INT KEYCOUNT;

і, отже, мається масив пар. Опис структури

STRUCT KEY {

CHAR *KEYWORD;

INT KEYCOUNT; } KEYTAB [NKEYS];

визначає масив KEYTAB структур такого типу і відводить для

їх пам'яті. Кожен елемент масиву є структурою. Це можна було б записати і так:

STRUCT KEY {

CHAR *KEYWORD;

INT KEYCOUNT; };

STRUCT KEY KEYTAB [NKEYS];

Тому що структура KEYTAB фактично містить постійний набір імен, то легше всього ініціалізувати її один раз і для всіх членів при визначенні. Ініціалізація структур цілком аналогічна попереднім ініціалізаціям - за визначенням випливає, що у фігурних дужках список ініціалізаторів:

STRUCT KEY {

CHAR *KEYWORD;

INT KEYCOUNT; } KEYTAB[] ={

"BREAK", 0,

"CASE", 0,

"CHAR", 0,

"CONTINUE", 0,

"DEFAULT", 0,

/* ... */

"UNSIGNED", 0,

"WHILE", 0

};

Ініціалізатори перелічуються парами відповідно членам структури. Було б більш точно узяти у фігурні дужки ініціалізатори для кожного "рядка" чи структури в такий спосіб:

{ "BREAK", 0 },

{"CASE", 0 },

. . .

Але коли ініціалізатори є простими змінними чи символьними рядками і усі вони присутні, то у внутрішніх фігурних дужках немає необхідності.

Лекція 9

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]