- •Програмування і алгоритмічні мови Конспект лекцій
- •Луцьк 2004
- •Лекція 1 Основи мови с. Оператори введення та виводу.
- •Імена змінних та типи і розміри даних. Арифметичні та логічні оператори. Оператори присвоєння.
- •Лекція 3 Масиви. Масиви літер.
- •Умовні оператори. Інкриментні та декрементні оператори.
- •Цикл For
- •Лекція 6 Цикли While, Do-while.
- •Препроцесор. Рекурсія.
- •Структури. Масив структур.
- •Основні відомості про функції.
- •Змінні і правила дії областей у функціях
- •Головні файли.
- •Масиви в якості аргументів функції.
- •Структури в якості аргументів функції
- •Вказівники і адреси
- •Масиви вказівників
- •Вказівники на структуру
- •Лекція 17 Використання вказівників у якості аргументів функцій
- •Лекція 18 Доступ до файлів
- •Методичне видання
- •“Автоматизоване управління технологічними процесами”
- •Тир.50 прим. Зам.1516
- •43018, М.Луцьк, вул. Львівська, 75
Препроцесор. Рекурсія.
В мові 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
