Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КТіП Лекції 20110516 (1).doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.32 Mб
Скачать
    1. Директиви #ifdef, #ifndef

Ще одним способом організації умовної компіляції є використання директив #ifdef (if defined – за умови визначеності) і #ifndef (if not defined – за умови невизначеності). Синтаксис їх однаковий:

#ifdef ім’я_макросу

фрагмент_програми

#endif

#ifndef ім’я_макросу

фрагмент_програми

#endif

Обидві директиви перевіряють, чи був макрос, ім’я якого задається в цій директиві, попередньо визначений директивою #define. При цьому не вимагається, щоб макрос мав повне визначення, достатньо оголошення

#define ім’я_макросу

Фрагмент програми, обмежений директивами #ifdef … #ifndef буде компілюватись за умови, що ім’я макросу попередньо визначене. Дія директиви #ifndef протилежна – фрагмент програми передається на компіляцію, якщо заданий макрос не визначений.

Умовну компіляцію можна використовувати для налагодження програм. Зокрема, в текст програм можна включити ряд контрольних перевірок і повідомлень, що допоможуть відстежити процес виконання програми. Наприклад:

#include <iostream>

using namespace std;

#define DEBUG

int main() {

int a = 123;

#ifdef DEBUG

cout << "a = " << a << endl;

#endif

}

Таких контрольних точок можна створити в програмі декілька. Коли від лагодження програми завершене, достатньо закоментувати директиву #define DEBUG або використати директиву #undef DEBUG.

Директиви #ifdef і #ifndef використовують в заголовних файлах для захисту програми від повторних включень заголовних файлів, які можуть виникнути через вкладення директив #include. Оголосимо структуру для збереження інформації про студентів в окремому файлі:

// student.h

#ifndef STUDENT_H

#define STUDENT_H

struct student {

int id;

int rating;

student * next;

};

#endif

#include <iostream>

#include "student.h"

using namespace std;

int main() {

struct student * p;

У разі повторного підключення файлу student.h макрос STUDENT_H вже буде визначеним і директива #ifndef пропустить препроцесування вмісту файлу.

Перевірити, чи ім’я заданого макросу визначене, можна також за допомогою операції defined, яка застосовується в виразах умови директив #if i #elif і має такий синтаксис:

defined ім’я_макросу

Якщо даний макрос був попередньо визначений, то результат операції буде істинний. До результатів цієї операції можна застосовувати логічні операції !, &&, ||. Попередній приклад можна записати так:

#if !defined STUDENT_H

#define STUDENT_H

struct student {

int id;

int rating;

student * next;

};

#endif

За допомогою цієї операції можна перевіряти визначеність декількох макросів:

#if defined A && defined B

#endif

  1. Функції

    1. Структура функції

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

Використання функцій дає змогу структурувати програму – поділити складні обчислювальні і/або інформаційні процеси на окремі складові частини, виділити основні кроки в алгоритмі розв’язування задачі, а вже потім розкрити деталі їх програмної реалізації в окремних функціях. Завдяки функціям можна уникнути багаторазового запису одних і тих самих дій і скористатися тим кодом, який був створений раніше, в тому числі бібліотеками систем програмування.

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

Функція описується синтаксичною конструкцією такого виду:

тип_значення_функції ім’я_функції ( оголошення_параметрів ) {

тіло_функції

}

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

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

Після імені функції вказують круглі дужки, в яких оголошується список параметрів функції – їх називають формальними параметрами або аргументами функції. У функції може бути порожній список параметрів, але круглі дужки, які є ознакою функції, вказувати обов’язково. Відсутність параметрів функції можна позначати не порожніми дужками, а ключовим словом void. В цьому випадку компілятор отримує інформацію про те, що виклик цієї функції повинен виконуватися без вказання фактичних параметрів, тобто тих параметрів, що задаються в звертанні до функції.

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

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

Функція завершує свою роботу, коли виконані всі оператори її тіла та досягнуто кінця функції або коли зустрінеться оператор return. Якщо тип значення функції – це void, то вона не повертає значення і оператор return для неї не обов’язковий. Але при необхідності його можна використовувати для переривання роботи функції. Наприклад:

#include <iostream>

using namespace std;

void PrintSqrt( double x ) {

if ( x < 0 ) {

cout << "x < 0" << endl;

return;

}

cout << sqrt( x ) << endl;

}

int main() {

PrintSqrt( -1. );

PrintSqrt( 4 );

}

В цьому прикладі при виконання умови x < 0 на екран буде виведене відповідне повідомлення, після цього виконання функції буде завершене, управляння передане в точку її виклику.

Якщо функція повертає значення, тобто її тип відмінний від void, це значення має бути передане через вираз, записаний в операторі return. Значення виразу перетворюється до типу, заданого в заголовку функції, і передається в точку програми, з якої була викликана функція. Операторів return всередині функції може бути декілька, виконання функції завершується при виконання першого оператора return.

#include <iostream>

using namespace std;

int sum( int a, int b ) {

int t;

t = a + b;

return t;

}

int max( int a, int b ) {

if ( a > b )

return a;

return b;

}

int main() {

int x = 3, y = 4;

cout << sum( x, y ) << endl;

cout << max( 2, 3 ) << endl;

}