Попередня сторінка Зміст Наступна сторінка Електронні посібники ВНТУ
ЛАБОРАТОРНА РОБОТА № 6
ФУНКЦІЇ
Мета роботи
- Дослідити принципи побудови функцій користувача, основні складові функцій, прототипи, оголошення та опис функцій.
- Дослідити правила розробки рекурсивних функцій.
- Навчитися розробляти і використовувати на практиці власні функції для вирішення завдань, які стоять перед розробником програм.
ТЕОРЕТИЧНІ ВІДОМОСТІ
Поняття функції та її склвдові
Функція – поіменована послідовність описів і операторів, яка виконує деяку закінчену послідовність дій. Будь-яка функція складається із заголовка (оголошення функції) і тіла (визначення функції).
Оголошення функції описує її прототип (іноді кажуть "сигнатура").
Прототип функції оголошується наступним чином:
Тип Повернення Ім’я Функції (Список Оголошених Параметрів);
Тут Тип Повернення – тип даних, що повертається функцією. Якщо він не зазначений, то за замовчуванням вважається, що повертається тип іnt.
Список Оголошених Параметрів задає тип і ім'я кожного з параметрів функції, розділених комами (ім'я параметра можна опускати). Список параметрів функції може бути порожнім. Прикладипрототипів функцій:
double мах (double parl, double par2);
int swap(int, int) ;
void func() ;
Визначення функції складається з її заголовка і власне тіла, вкладеного у фігурні дужки і такого, що має смислове навантаження. Якщо функція повертає будь-яке значення, в тілі функції обов'язково повинен бути присутнім оператор повернення з параметром того ж типу.
Тип Поверн Ім’я Функції (Список Оголошених Параметрів)
{
// тіло функції
}
Виклик функції – вказівка ідентифікатора функції (її імені), за яким в круглих дужках слідує список аргументів, розділених комами.
double maxValue = мах (2.5, 1235.2);
int j = swap(10, 2);
func();
Функції, що не повертають значення
Це функції типу void – ті, що не повертають значення – можуть розглядатися, як деякий різновид команд, реалізований особливими програмними операторами. Оператор func(); виконує функцію void func() , тобто передасть керування функції, доки не виконаються усі її оператори. Коли функція поверне керування в основну програму, тобто завершить свою роботу, програма продовжить своє виконання з того місця, де розташовується наступний оператор за оператором func().
Якщо функція повертає значення типу void, то її виклик слід організовувати так, щоб значення, яке повертається, не використовувалося. Тобто, таку функцію не використовують у правій частині виразу.
Рекурсивні функції
Рекурсія – це спосіб організації обчислювального процесу, при якому функція в ході виконання операторів звертається сама до себе.
Функція називається рекурсивною, якщо під час її роботи можливий повторний її виклик безпосередньо (прямий виклик) або шляхом виклику іншої функції, в якій міститься звернення до неї (непрямий виклик).
Прямою (безпосередньою) рекурсією називається рекурсія, при якій всередині тіла деякої функції міститься виклик тієї ж функції.
void fn(int i) { ... fn(i); ... }
Непрямою рекурсією називається рекурсія, що здійснює рекурсивний виклик функції шляхом ланцюга викликів інших функцій. При цьому всі функції ланцюга, що здійснюють рекурсію, вважаються рекурсивними.
void fnA(int i){
... fnB(i); ...
}
void fnB(int i) {
... fnC(i); ...
}
void fnC(int i) {
... fnA(i); ...
}
Для ілюстрації рекурсії наведемо функцію обчислення n!:
double fact(int n)
{
if (n<=1) return 1;
return (fact(n-1)*n);
}
void main()
{ int n;
double value;
printf("N=");
scanf("%d",&n);
value=fact(n);
printf("%d! = %.50g",n,value);
getch();
}
Аргументи функції за замовчуванням
С++ допускає при виклику функцій опускати деякі її параметри. Досягається це зазначенням в прототипі функції значень аргументів за замовчуванням. Наприклад, функція, прототип якої наведено нижче, може при виклику мати різний вигляд в залежності від ситуації.
// Прототип функції:
void ShowInt(int i,bool Flag=true,char symbol='\n');
// Виклик функції ShowInt:
ShowInt(A, false, 'a');
ShowInt(B, false);
ShowInt(C);
Передавання параметрів у функцію
Механізм передавання параметрів є основним способом обміну інформацією між функціями. Параметри, перераховані в заголовку опису функції, називаються формальними параметрами (або просто параметрами), а записані в операторі виклику функції – фактичними параметрами (або аргументами).
Існує два способи передачі параметрів у функцію: за значенням і за адресою.
При передаванні за значенням в стек заносяться копії значень аргументів, і оператори функції працюють з цими копіями. Доступу до початкових значень параметрів у функції немає, а, отже, немає і можливості їх змінити.
При передаванні за адресою в стек заносяться копії адрес аргументів, а функція здійснює доступ до комірок пам'яті за цими адресами і може змінити значення аргументів:
#іnclude <iostream.h>
void f(int i, int* j, int& k);
int main()
{
int i=1,j=2,k=3;
cout <<"i j k\n";
cout<<i<<" "<<j<<" "<<k<<'\n'; // Результат: 1 2 3
f(i,&j,k);
cout<<i<<" "<<j<<" "<<k; // Результат: 1 3 4
return 0;
}
void f(int і, int* j, int& k)
{
i++; (*j)++; k++;
}
Перший параметр (і) передається за значенням. Його зміна в функції не
впливає на вихідне значення. Другий параметр (j) передається за адресою за допомогою покажчика, при цьому для передаванні у функцію адреси фактичного параметра використовується операція взяття адреси, а для отримання його значення в функції потрібна операція розіменування. Третій параметр (k) передається адресою за допомогою посилання.
При передаванні за посиланням у функцію передається адреса зазначеного при виклику параметра, а всередині функції всі звернення до параметру неявно розіменовуються. Використання посилань замість покажчиків, по-перше, покращує читабельність програми, позбавляючи від необхідності застосовувати операції одержання адреси та розіменування; і, по-друге, не вимагає копіювання параметрів, що важливо при передаванні структур даних великого обсягу.
Якщо потрібно заборонити зміну параметра усередині функції, використовуєтьсямодифікатор const:
іnt f(const char*);
char* t(char* a, const int* b);
Масиви як параметри функції
Усі параметри, за винятком параметрів типу покажчик та масив, передаються за значенням. Це означає, що під час виклику функції їй передаються тільки значення змінних. Сама функція не в змозі змінити цих значень у функції, що їх викликає.
Одновимірний масив як параметр
Ім’я масиву є покажчиком на його нульовий елемент, тому у функцію масиви передаються за покажчиком. Кількість елементів масиву може передаватися окремим параметром.
Приклад 1. Програма підраховує, в якому з двох масивів кількість додатних елементів більша.
int n_posit(int* mas, int n);
int main()
{ int n,i;
cout<<"Input count of symbols: ";
cin>>n;
int *A = new int[n];
int *B = new int[n];
for (i=0; i<n; i++)// генеруємо елементи масивів
{ A[i] = rand()%100 – 50;
B[i] = rand()%200 – 100;
}
cout << "\n\nA: ";// виводимо масиви на екран
for (i=0; i<n; i++) cout << " "<<A[i];
cout << "\n\nB: ";
for (i=0; i<n; i++) cout << " "<<B[i];
// порівнюємо кількість додатних елементівтів
if (n_posit(A,n) > n_posit(B,n))
cout << "\n\nFirst array A is winner!";
else if (n_posit(A,n) < n_posit(B,n))
cout << "\n\nSecond array B is winner!";
else cout << "\n\nEqual count!";
_getch();
return 0;
}
int n_posit(int* mas, int n)
{ int count = 0;
for (int i=0; i<n; i++)
if (mas[i]>0) count++;
return count;
}
Результат роботи програми:
Рядок (масив символів) як параметр функції
На відміну від передавання у функцію звичайного масиву, для рядка немає необхідності окремим параметром передавати розмірність масиву. Можна визначати кінець рядка за нуль-символом ('\0').
Приклад 2. Програма отримує рядок і виводить його посимвольно, вставляючи між сиволами знаки підкреслювання.
void outMyText(char* str);
int main()
{ cout<<"\n InString: ";;
char str[80];
gets(str);
outMyText(str);
_getch();
return 0;
}
void outMyText(char* s)
{ cout << "\n\n\n OutString: ";
int i = 0;
while(s[i] != '\0')
{ cout << "__" << s[i];
i++;
}
}
Результат роботи програми:
Двовимірний масив в якості параметра функції
Приклад 3. Виведення масиву на екран по рядках.
void printArray(int** mas, int n, int m);
int main()
{ int n,m,i;
cout<<"\n Input n m: "; cin>>n>>m;
int** A = new int*[n];
// генеруємо елементи масивів
for (i=0; i<n; i++)
{ A[i] = new int[m];
for (int j=0; j<m; j++) A[i][j] = rand()%200 – 100;
}
printArray(A,n,m);
_getch();
return 0;
}
void printArray(int** mas, int n, int m)
{ cout << "\n\nARRAY:\n\n";
for (int i=0; i<n; i++)
{ cout<<"\n";
for (int j=0;j<m;j++) printf("%6i",mas[i][j]);
}
}
Результат роботи програми:
Порядок виконання роботи
- Ознайомитись з теоретичним матеріалом.
- Дослідити процес реалізації завдань прикладів, відлагодити наведені програми на своєму комп’ютері.
- Розробити власні програми, які реалізу.ть індивідуальні завдання.
- Результати розробки представити у звіті, який матиме такі складові:
- варіант, завдання;
- загальна схема роботи програми (для першого завдання – без детальних схем функцій, для другого – включаючи схеми функцій);
- схема взаємозв’язків функцій у програмі;
- лістинг програми (з коментарями);
- результати виконання програми;
- висновки.
Варіанти індивідуальних завдань
Задача 1. Розробити програму, яка працюватиме наступним чином. Головна функція програми повинна викликати інші функції, створені за результатами попередніх лабораторних робіт (сформувати повне завдання):
- функція, яка повертає випадкове число з вказаного діапазону (границі інтервалу – аргументи функції) – лабораторна робота №2 (задача 1);
- функція, яка виконує завдання лабораторної роботи №3 (задача 1);
- функція, яка виконує завдання лабораторної роботи №4 (задача 1);
- функція, яка реалізує меню для керування роботою програми;
- інші функції, необхідні для виконання.
Задача 2. Розробити програму для реалізації індивідуального завдання.
1 | Написати функцію, яка виводить на екран суцільний прямокутник, створений із заданих символів C (наприклад, '#'), сторони прямокутника визначаються змінними W та H. Наприклад, якщо C='*', W=5, H=5, то функція виведе показане зображення. |
***** ***** ***** ***** ***** |
3 | Напишіть функцію, яка виводить ціле число між 1та 32767 і друкує це число як послідовність цифр, між якими стоять два пробіли. Наприклад, ціле число 4562 повинно бути надруковане так: 4 5 6 2. | |
2 | Функція отримує час у вигляді трьох цілих аргументів (години, хвилини, секунди) і повертає кількість секунд з моменту, коли на годиннику було 0 годин. Використайте цю функцію для підрахунку часу в секундах між двома моментами часу. | |
3 | Напишіть функцію, яка виводить ціле число між 1та 32767 і друкує це число як послідовність цифр, між якими стоять два пробіли. Наприклад, ціле число 4562 повинно бути надруковане так: 4 5 6 2. | |
4 | Ціле число називається досконалим (рос. совершенным), якщо сума його дільників, включаючи 1 (але не саме число) , дорівнює цьому числу. Наприклад, число 6 = 1+2+3 є досконалим. Напишіть програму perfect, яка визначає, чи є число досконалим. Використайте цю функцію у програмі, яка знаходить і друкує усі досконалі числа з діапазону від 1 до 1000. | |
5 | Ціле число називається простим, якщо воно ділиться на 1 і на самого себе. Наприклад, числа 2,3,5 і 7 є простими, а 2,6,8 і 9 – ні. Напишіть функцію, яка визначає, чи є число простим. Використайте цю функцію у програмі, яка знаходить і друкує усі прості числа у діапазоні від 1 до 10000. | |
6 | Напишіть функцію, що отримує ціле значення і повертає число з оберненим порядком цифр. Наприклад, для 7631 функція повинна повернути 1367. | |
7 | Напишіть функцію, яка вводить бали, зароблені студентом, а повертає оцінку за шкалою ECTS: | |
8 | Напишить функцію distance, яка обраховує відстань між двома точками з координатами (х1, у1) і (х2, у2). Усі числа і повернене значення повинні бути дійсними. Використайте цю функцію у програмі, яка обчислює площу трикутника за формулою Герона. | |
9 |
Напишіть програму, яка допоможе школяру вивчити таблицю множення. Згенеруйте два додатних однорозрядних числа (окрема функція). Програма виводить, наприклад, питання: "Скільки буде 5 на 6?". Школяр повинен відповісти. Якщо відповідь правильна, програма друкує "Молодець! Дуже добре!" і після цього задаю наступне питання на множення. Якщо відповідь неправильна, програма друкує: "Невірно! Спробуйте знову …", до тих пір, поки відповідь не буде правильною. Розроблювана функція повинна отримувати три числа: два множники та число-віповідь школяра, і друкувати потрібну фразу. |
|
10 | Напишіть функцію muliply для двох цілих, яка визначатиме, чи кратне друге число першому, Функція повинна отримувати два цілих аргументи і повертати 1 (true), якщо друге число кратне першому, і 0 (false) в іншому випадку. Використайте цю функцію у програмі, яка вводить серію пар цілих чисел. | |
11 |
Напишіть програму, яка грає у гру "Вгадай число" наступним чином: ваша програма "задумує" число (випадкове число у діапазоні від 1 до 1000), яке треба вгадати. Далі програма друкує: У мене є число між 1 та 1000. Відгадайте і введіть ваше число… Далі гравець вводить перше число. Програма відповідає однією з фраз: Чудово! Ви вгадали число! Будете грати далі? Занадто мале. Спробуйте ще раз. Занадто велике. Спробуйте ще раз. При реалізації гри необхідно написати функцію, яка приймає два числа: "задумане" і відповідь гравця, а після аналізу друкувати одну з фраз. |
|
12 | Написати функцію, яка виводить на екран трикутник, створений із заданих символів C (наприклад, '#'), основа трикутника визначається змінною W. Наприклад, якщо C='*', W=5, то функція виведе показане зображення. |
***** **** *** ** * |
13 | Напишіть програму, яка буде використовувати функцію, що обчислює скалярний добуток двох векторів дійсних чисел, що мають однакову розмірність. | |
14 | Розробити функцію, яка змінює значення двох заданих дійсних змінних. Перша змінна повинна отримати значення суми початкових даних, а друга – значення їх різниці. | |
15 | Напишіть програму, яка вводить довільні натуральні числа і визначає, чи є введене число паліндромом. Для визначення, чи є число паліндромом, написати окрему функцію, яка приймає число і повертає true або false. Число називається поліндромом, якщо воно сліва направо і справа наліво читається однаково. Наприклад, числа 232, 7667 і 34543 є поліндромами, а числа 123 і 45 – ні. |
* Задача 3. В програмі святкування дня народження кафедри захисту інформації заплановано 7 номерів. Аліса, Боб і Карл приймають участь у цих виступах. Оскільки вони – люди творчі, тому виступи, які вони бачать до свого впливають на рівень їх натхнення. Для ідеального виступу Алісі необхідно 8 одиниць натхнення, Бобу – 9, Карлу – 7. В інших випадках якість їх виступу буде пропорційно менша за можливий максимум.
Оскільки Аліса, Боб та Карл мають різні вподобання, тому однакові номери надихають їх по-різному.
Студент | Музика | Лірика | Гумор |
Аліса | 4 | 2 | 3 |
Боб | 3 | 3 | 2 |
Карл | 1 | 2 | 4 |
Внаслідок отримання чудового подарунку від Аліси та Боба на власний день народження Карл ще до початку вистави має 3 одиниці натхнення.
Для вистави Аліса приготувала гру на кобзі, Боб написав ліричного вірша про кафедру і студентське життя, а Карл бере участь у жартівливій сценці про викладачів.
Написати програму, яка визначатиме якість виступів (у відсотках) та рівень натхнення Аліси, Боба та Карла після святкування дня народження кафедри, за умови, що їх власні виступи їх не надихають (оскільки вони себе не бачать, коли виступають).
Варіант | Номери | ||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | |
1 | Музика | Гумор | Карл | Аліса | Лірика | Боб | Гумор |
2 | Лірика | Музика | Гумор | Лірика | Аліса | Карл | Боб |
3 | Гумор | Лірика | Музика | Боб | Гумор | Аліса | Карл |
4 | Лірика | Гумор | Лірика | Музика | Боб | Аліса | Карл |
5 | Музика | Лірика | Аліса | Гумор | Лірика | Боб | Карл |
6 | Музика | Лірика | Боб | Аліса | Лірика | Карл | Гумор |
7 | Лірика | Гумор | Карл | Музика | Боб | Гумор | Аліса |
8 | Гумор | Музика | Гумор | Боб | Аліса | Лірика | Карл |
9 | Лірика | Лірика | Музика | Карл | Боб | Аліса | Гумор |
10 | Музика | Гумор | Лірика | Гумор | Боб | Карл | Аліса |
11 | Музика | Музика | Карл | Аліса | Лірика | Боб | Гумор |
12 | Лірика | Музика | Боб | Гумор | Аліса | Лірика | Карл |
13 | Гумор | Гумор | Боб | Карл | Лірика | Аліса | Музика |
14 | Лірика | Музика | Гумор | Музика | Карл | Аліса | Боб |
15 | Музика | Лірика | Музика | Гумор | Боб | Карл | Аліса |
Контрольні питання
- Що називають функцією? Що таке опис функції?
- Що таке прототип функції? Де його розміщують у програмі?
- Які символи оточують тіло функції? Які символи оточують аргументи функції?
- Чи обов’язково в прототипах функцій вказувати ідентифікатори змінних?
- Як відбувається звернення до функції?
- Яке ключове слово використовується в заголовку функції, щоб показати, що функція не повертає нічого і немає жодного параметра?
- Чи кожна функція повинна мати оператор повернення?
- Нведіть специфікатори класу пам’яті.
- Що таке локальні змінні? Що означає специфікатор пам’яті auto?
- Що таке глобальні змінні? Що означає специфікатор пам’яті external?
- Що означає специфікатор пам’яті static? Чи можуть статичні змінні бути локальними?
- Чи можна у функцію передавати параметри за замовчуванням?
- Що таке фактичні параметри функції?
- Що таке формальні параметри?
- Чим відрізняються фактичні параметри від формальних?
- Чи можуть ідентифікатори фактичних і формальних параметрів співпадати?
- Чи обов’язково кількість фактичних і формальних параметрів повинні співпадати?
- Що таке рекурсивна функція? Навести приклад.
- Що означає, що параметри передаються у функцію за значенням?
- Що означає, що параметри передаються у функцію за покажчиком?
- Як передати у функцію масив? Навести приклад.
- Як передати у функцію рядок символів? Навести приклад.
- Що означають параметри головної функції програми?
- Чи може глобальна змінна бути розташована у тілі програми?
- Чи можна у середині однієї функції оголошувати іншу функцію?
- Що таке вбудовані функції? Коли вони використовуються?