You are on page 1of 72

Міністерство освіти і науки України

Національний технічний університет України


“Київський політехнічний інститут”
Кафедра автоматизованих систем обробки інформації та управління

Процедурно-орієнтоване програмування мовами С/С++

Методичні вказівки до лабораторних занять


з дисципліни “Алгоритмізація та програмування”

для студентів напряму “Комп’ютерні науки”


спеціальності
“Інформаційні управляючі системи та технології”

Київ 2010

3
Типи даних. Функції введення - виведення.
Обчислення виразів
Лабораторна робота 1
Мета роботи.
1. Вивчити особливості використання вбудованих типів даних: char, int, long,
short, float, double, unsigned char, unsigned int, unsigned long.
2. Вивчити особливості використання функцій введення - виведення.
3. Навчитися застосовувати стандартні математичні функції.
1.1 Теоретичні відомості
1.1.1. Структура програми
Програма складається з директив препроцесора, функцій, зовнішніх описів
програми, коментарів.
Препроцесор - програма, що є складовою частиною компілятора і виконує
підключення стандартних або особистих файлів користувача до основної програми,
формування макровизначень, умовну компіляцію тощо.
Розрізняють директиви:
включення
#include <ім’я.h >
#include "ім’я.h"
макровизначення
#define ім’я значення
умовної компіляції
#if вираз
#else
#elif вираз
#endif
Директива формату #include <ім’я.h> використовується для включення
стандартних файлів заголовків з каталогу include до програми користувача. Ці файли
містять прототипи функцій, які користувач може використовувати у власній програмі як
стандартні функції.
Директива формату #include "ім’я.h" використовується для включення власних
файлів користувача до поточного коду.
1.1.2 Структура функцій програми
Функція - це іменована частина програми, що виконує логічно завершений набір
дій та може викликатися з будь-якого місця програми, якщо це відповідає синтаксису
програми. Функція складається з заголовка і тіла. Формат функції такий:
тип_ значення _що_повертається ім’я_функції (параметри) //заголовок
{ // тіло функції }
Одна з функцій програми має ім’я main(). Ця функція є точкою входу до
програми. З цієї функції починається виконання програми. Якщо параметри відсутні, то в
заголовку функції записуються тільки круглі дужки. Наприклад,
тип_ значення _що_повертається main()
{ ... //тіло функції }

4
Тіло функції містить оголошення констант, змінних і оператори відповідно до
алгоритму. Оголошення можуть бути в довільному місці, але до першого звертання до
змінної.
1.1.3 Правила синтаксису
{ } - операторні дужки. Вони об’єднують декілька операторів в один блок,
визначають початок і кінець блоку та функції;
; - кінець оператора;
, - роздільник при перерахуванні програмних об’єктів;
( ) - містять параметри функцій або умови логічних та циклічних операторів;
/* */ - містять коментар, що розміщується на декількох рядках;
// - коментар, що розміщується в одному рядку, використовується в С++.
1.1.4. Типи даних
Усі дані поділяються на змінні та константи. Кожна змінна має свій ідентифікатор
або своє ім’я. Кожне ім’я змінної відповідає певній області оперативної пам’яті
комп’ютера. Кожна змінна характеризується іменем, типом, обсягом оперативної пам’яті
та діапазоном значень.
Таблиця 1.1 Характеристика типів змінних
Тип Назва типу Обсяг Діапазон значень
оперативної
пам’яті

сhar Цілий тип 8 бітів -128 ... +127


signed char Цілий із знаком 8 бітів -128 ... +127
unsigned char Без знаковий цілий 8 бітів 0 ... 255
short int Цілий короткий 16 бітів -32768 ... +32767
unsigned int Без знаковий цілий 32 бітів 0 ... 65535
int Цілий 32 бітів -2147483648 …
+2147483647
long int Цілий довгий 32 бітів -2147483648 …
+2147483647
unsigned long Цілий довгий без знаковий 32 бітів 0 ... +429496729

float З плаваючою крапкою 32 бітів 3.4 *10^38 …


3.4 *10^-38
double З плаваючою крапкою 64 бітів 1.7 *10^-308 …
довгий 1.7 *10^308
long double З плаваючою крапкою 80 бітів 3.4 *10^-4932 …
довгий 3.4 *10^4932
Приклад оголошення змінних:
int a; float b,c; char litera; int index=1;

5
1.1.5. Функції введення та виведення даних
Для виконання дій над даними користувача необхідно їх ввести з клавіатури. Для цього використовується стандартний
потік вводу stdin. Для відображення результатів на екрані необхідно застосовувати стандартний потік виводу stdout. Введення та
виведення даних здійснюється за допомогою функцій введення та виведення, формати яких приведені у таблиці 1.2.
Таблиця 1.2 Функції введення та виведення
Функція Формат введення та Призначення Приклад Заголовни Результат, що
виведення й файл повертається функцією
_сprintf() int _cprintf ( формат, Виведення на консоль значень int с; сonio.h Значення типу int,
_cprint("%d",c);
apг1, apг2, ...) аргументів згідно з форматом дорівнює кількості
виведення. виведених символів

_cscanf() int _cscanf (формат, Введення з консолі значень int a; char сonio.h Значення типу int
NAME[5];
арг1,aрг2,...) змінних згідно з форматом і дорівнює кількості
_cscanf ("%s",
присвоєння значень Name); змінних, що отримали
аргументам. Аргументами є _cscanf ("%d", значення. При
адреси змінних в оперативній &a); невдалому скануванні
пам’яті. повертається значення
EOF
_cputs() int _cputs (const char Виведення на консоль рядка char NAME[5]; conio.h У випадку успіху
_cputs(NAME);
*str); символів. Не додається символ повертається 0
_cputs("Hello");
кінця рядка ‘\0’. Borland C++
використовує cputs()
_cgets() char *_cgets (char Введення з консолі char a[5]; conio.h Значення типу int, що
_cgets(a);
*str); послідовності символів до дорівнює покажчику на
символу “кінець рядка” (‘\0’), символ з індексом 2
(str[2]).
getch() int getch(void); Введення символу з консолі без int c; c=getch(); conio.h Код введеного з
відображення на екрані. Не клавіатури символу

6
Функція Формат введення та Призначення Приклад Заголовни Результат, що
виведення й файл повертається функцією
використовується для Win32.
putch() int putch(int c); Виведення на консоль символу. putch('В’); conio.h Повертається
putch(getch());
Не використовується для Win32 надрукований символ
або значення EOF при
невдалому виведенні.
getchar() int getchar(void); Введення символу із int ch; stdio.h Повертається код
ch=getchar();
стандартного вхідного файлу введеного символу або
stdin. значення EOF

putchar() int putchar(int c); Виведення у стандартний putchar(getch()); stdio.h Повертається символ
вихідний файл stdout символу. або значення EOF при
невдалому виводу
gets() char *gets ( char *s); Введення із стандартного char line[80]; stdio.h Покажчик на перший
gets(line);
вхідного файлу stdin рядка і символ рядка або
розміщення його по покажчику NULL при невдалому
*s введенні
puts() int puts (const char Виведення у стандартний char b[80]; stdio.h Повертається
puts(b);
*s); вихідний файл stdout рядка і невід’ємне значення
доповнення його символом або EOF при невдалому
нового рядка ‘\n’ виведенні
printf() int printf (const char Виведення у стандартний int a; float b; stdio.h Повертається кількість
char str[10];
*format, вихідний файл stdout значень виведених байтів або
printf("%d %f
argument, ...); аргументів згідно з форматом %s", a.b.str); від’ємне значення при
виведення невдалому виведенні

scanf() int scanf (const char Введення із стандартного char AME[20]; stdio.h Повертається кількість
int a;
7
Функція Формат введення та Призначення Приклад Заголовни Результат, що
виведення й файл повертається функцією
*format, address, ...); вхідного файлу значень змінних scanf("%s", AME); змінних, що отримали
scanf("%d", &a);
згідно з форматом і розміщення значення. При
їх за вказаними адресами у невдалому скануванні
оперативній пам’яті. повертається значення
EOF
sprintf() int sprintf (char *str, Розміщення у рядку символів char str[3] stdio.h Повертається кількість
sprintf(str,"%d",
const char *format, значень аргументів із пам’яті виведених символів.
13);
argument, ...); згідно з шаблоном.
Використовується для
перетворення типів даних
sscanf() sscanf (рядок, Читання із рядка у адреси int a; float b; stdio.h Повертається кількість
char str[5];
формат, арг1, ...); пам’яті згідно з форматом введених символів або
sscanf(str,"%d
шаблонів. Використовується %f", &a, &b); EOF при невдалому
для перетворення типів введенні

Специфікації форматів, що використовуються у функціях форматного введення та виведення даних, приводяться у


табл. 1.3.

8
Таблиця 1.3. Специфікації форматів
Функція Формат
scanf() %[*] [ширина] тип
printf() % [прапорець] [ширина] [.точність] тип
Значення полів формату:
% - символ формату.
* - ігнорується поле вводу, дані не зберігаються.
тип - символ, який визначає типи даних, що вводяться та виводяться.
прапорець - символи, які управляють вирівнюванням виводу знаків, пропусків,
десяткових точок, восьмирічних та шістнадцятирічних префіксів.
ширина - параметр, який визначає мінімальне число виводу символів.
точність – параметр, який визначає максимальне число символів, що друкуються
для цілих чисел, та кількість цифр після десяткової точки для даних типу float, double.
Таблиця 1.4 Специфікації деяких типів
Символ Тип аргументу
формату
c char
d int
i int (десятковий, восьмирічний, шістнадцятирічний)
e, f float, double
s Рядок символів
n Покажчик на цілий тип
p Покажчик на тип void (задає сегмент та зміщення)
Специфікації прапорців у функціях форматного виведення
+ Виведення знаків +/-, якщо використовується знаковий тип
- Вирівнювання даних зліва
Таблиця 1.5 Використання класів потоків для операцій вводу, виводу
Формат Призначення Приклад Заголовний
файл
cin >> Зумовлений потік введення, >> - char Name[20]; istream
cin >> Name; iostream
операція правого зсуву
cout << Зумовлений потік виведення, << - int c; char f; ostream
cout<< “Hello”; iostream
операція лівого зсуву
cout<<c<<f;
Таблиця 1.6 Математичні функції

Функція Призначення Приклад Бібліотека Тип


abs Модуль аргументу abs(c); abs(-b); stdlib.h int
acos Арккосинус acos(0.5) math.h double
asin Арксинус asin(1); math.h double
atan Арктангенс atan(1.0); math.h double
cos Косинус cos(3.14); math.h double
exp Експонента exp(1); math.h double
log Натуральний логарифм log(exp(3) math.h double
log10 Десятковий логарифм log10(100) math.h double
pow Ступінь числа x^y pow(x,y) math.h double
sin Синус sin(3.1/6) math.h double
sqrt Корінь квадратний sqrt(144) math.h double
tan Тангенс tan(3.1/4) math.h double

9
1.2 Приклад програми
Умова задачі
Скласти програму, яка вводить дані різного типу з клавіатури та виводить дані на
екран. Типи даних відповідають таблиці 1.1. Використати функції вводу та виводу
відповідно до таблиці 1.2. Виконати розрахунок математичного виразу, використовуючи
математичні функції відповідно до таблиці 1.6. Сценарій роботи програми вимагає вивід
на екран повідомлень про необхідність вводу даних відповідного типу за допомогою будь-
яких функцій виводу. У відповідь на повідомлення, що з’являється на екрані, користувач
вводить дані відповідного до повідомлення типу.
Особливості використання функцій вводу та виводу
1. При введенні та виведенні даних за допомогою класів потоків з рядка, який має
символи пропусків, вводяться та виводяться символи тільки до першого символу
пропуску.
2. При введенні даних потоком використовується стандартний потік вводу stdin,
при виведенні потокових даних використовується стандартний потік виводу stdout.
3. Після введення символу за допомогою функцій getchar(), getche(),
getch() необхідно очищати буфер клавіатури, інакше наступний ввід даних буде
неможливий (необхідно опрацювати введення символу ENTER, використовуючи функцію
fflush(stdin)).
4. При введенні символу без відображення його на екрані натискувати клавішу
ENTER після символу непотрібно.
5. Для переведення курсору на новий рядок в процесі виведення даних на екран
використовується ESC-послідовність ‘\n’
6. Для отримання кінця рядка використовується ESC-послідовність ‘\0’
7. Для виконання табуляції курсору в процесі виведення даних на екран
використовується ESC-послідовність‘\t’.
8. При використанні функцій консольного виводу курсор не переводиться на
початок наступного рядка, тому користувач повинен використовувати ESC-послідовності
'\n' - перевід курсору на новий рядок, '\r' - перевід курсору на початок рядка.

10
Текст програми 1.1
#include<stdio.h> //бібліотека функцій введення та виведення
#include<conio.h> //бібліотека очищення екрана та іншого сервісу
#include<math.h> //бібліотека математичних функцій
#include<iostream> //бібліотека потоків вводу – виводу
using namespace std;
void main() //основна функція – точка входу до програми
{ //початок основної функції
char simbol;
puts("function puts():"); //вивід повідомлення на екран
puts("input simbol"); //вивід повідомлення на екран
putchar(getch()); //вивід символу, що не відображається
puts("\n repeat input simbol-function getch():");
//вивід повідомлення
simbol=getch(); //ввід символу з клавіатури
putchar(simbol); //вивід символу на екран
char str[20];
puts("\n input string - function gets():"); //вивід повідомлення
gets(str); // введення рядка
printf("functions printf(),puts(): str=");
// форматне виведення тексту
puts(str); // виведення рядка
printf("\r\n function printf(): str=%s \r\n",str);
//форматне виведення рядка
int i; float a,b,c;
puts("function scanf(),printf()");
printf("\n input integer i, float a,b,c \n"); // форматне виведення
scanf("%d%f%f%f",&i,&a,&b,&c); // форматне введення
printf("i=%d a=%f b=%f c=%e",i,a,b,c); // форматне виведення
puts("\n input string for sscanf() as %d %f %f or sprintf()");
char str1[20],str2[20]; float a1,b1,d;
fflush(stdin); // очищення буфера клавіатури
gets(str1); //ввід рядка з клавіатури
printf("string is: ");
puts(str1);
sscanf(str1,"%d %f %f",&i,&a1,&b1);
//введення із рядка за адресами змінних
printf("i=%d a=%f b=%e \n",i,a1,b1);
// вивід на екран для контролю введення
puts("function sprintf() does not display rezult");
sprintf(str2,"i=%d a=%f b=%e ",i,a1,b1); // виведення у рядок
puts("function puts():");
puts(str2);
d=(a+pow(b,3)-abs(a1-b1))/sqrt(sin(c*3)); // розрахунок виразу
puts("function printf():");
printf("d=(a+pow(b,3)-abs(a1-b1))/sqrt(sin(c*3))=%f",d);
char string[30]; //оголошення рядка
cout<<"\n input text"<<endl; //потоковий вивід
cin>>string; //потоковий ввід
cout<<" entered text is "<<"'"<<string<<"'"<<endl;
getch(); // затримка екрана

11
Результати виконання програми 1.1

Текст програми 1.2


#include <stdio.h> //бібліотека стандартних функцій вводу - виводу
#include <conio.h> //функції роботи з екраном
#include <math.h> //математичні функції
#include <iostream> //потоки вводу – виводу
#include <stdlib.h> //функція виходу з програми
using namespace std;
//=============== функція початку роботи =================== =====
void welcome(){
puts("Welcome to see the usage of input/output functions in C++!!!");
puts("Press any key..."); //вивід тексту
char a;
cin>>a; //чекати натискання на клавішу
}
//====функції putchar(),getchar(),putch(),getch(),puts(),gets()==
void f1(){
char str[15];
puts("Usage of functions putchar(),getchar():");
puts("Input any symbol"); //вивід тексту
char c;
c=getchar(); //ввід символу
putchar(c); //вивід символу
puts("\nUsage of functions putch(),getch():");
putch(getch()); //ввід символу без його відображення на екрані
puts("\nUsage of functions puts(),gets():");
puts("Input string");
gets(""); //зчитується символ '\n'
gets(str); //ввід рядка
puts(str); //вивід рядка
getch(); //чекати натискання на клавішу
}
//======================= функції cin,cout ==========================
void f2(){
int a;
puts("Usage of functions cin,cout:");
cout<<"Enter int a"<<endl; //потоковий вивід
cin>>a; //потоковий ввід

12
cout<<"\na^2="<<a*a<<endl;
getch(); //чекати натискання на клавішу
}

puts("Usage of sscanf(),sprintf()");
int a; float b,c;
//опис локальних змінних
char str1[15],str2[15];
puts("Input int,float,float:");
gets(str1);
//ввід рядка
sscanf(str1,"%d %f %f",&a,&b,&c); //запис даних з рядка за
// адресами змінних
puts("function sprintf() not display
rezult"); //вивід повідомлення
sprintf(str2,"a=%d b=%f c=%e -",a,b,c); //запис значень змінних у
// рядок
puts("Your string is");
puts(str2); //вивід рядка
}
//==================== функції sscanf(),sprintf() ===================
void f3(){
puts("Usage of sscanf(),sprintf()");
int a; float b,c; //опис локальних змінних
char str1[15],str2[15];
puts("Input int,float,float:");
gets(str1); //ввід рядка
sscanf(str1,"%d %f %f",&a,&b,&c);
//запис даних з рядка за адресами змінних
puts("function sprintf() not display rezult");
//вивід повідомлення
sprintf(str2,"a=%d b=%f c=%e -",a,b,c);
//запис значень змінних у рядок
puts("Your string is");
puts(str2); //вивід рядка
}
//======================приклад обчислення виразу =================
void f4(){
system("cls");//очищення екрана
puts("Usage of scanf(),printf()and math functions:\n");
float a,b,c,y;
puts("enter a, b!=0, c>-1(c!=0) :"); //вивід повідомлення
scanf("%f%f%f",&a,&b,&c); //форматний ввід даних
if ((b==0)||(c<=-1)||(c==0)) //умови існування виразу
{
printf("\nError!!! Try another time...\r\n");
exit(1); //переривання програми
}
y=abs(a/b-log(c))/sqrt(pow(c,5)+1)-cos(2*a)/atan(c)+sinh(a); //вираз
printf("Calculating...Press any key...\r");
getch(); //чекати натискання на клавішу
//вивід результатів
printf("abs(a/b-log(c))/sqrt(pow(c,5)+1)-cos(2*a)/atan(c)+sinh(a)=%e\r\
n",y);
puts("Good luck!!!");
}
//======================== головна програма 1.2 ====================
void main(){
welcome(); //функція початку програми
f2(); //функції putchar(),getchar(),putch(),getch(),puts(),gets()
f3(); //функції cin,cout
f1(); //функції sscanf(),sprintf()
f4(); //приклад обчислення виразу
}

13
Функції welcome та f4

Результати виконання програми 1.2


Функція F1() Функція F3()

1.3 Технологія виконання лабораторної роботи


1. Завантажити середовище Visual Studio.NET.
2. Створити новий консольний проект (Win32 Console Application) і додати до
нього файл з текстом програми (С++ Source File). Для цього виконати наступні дії:
3. Вибрати пункт меню FileNewProjectWin32 Console Application
4. Задати ім’я проекту в рядку вводу Project name
5. Вибрати місцезнаходження проекту в рядку Location, викликавши діалог
Browse
6. Натиснути кнопку OK, перейти на наступний етап
7. Вибрати вид проекту Empty project (пустий проект), натиснути на кнопку
Finish, потім на кнопку OK.
8. Створити новий вихідний файл за допомогою команди New меню File, на
вкладці Files вибрати тип файлу C++ Source Files, ввести ім’я файлу в рядок вводу File
name, натиснути кнопку OK.
9. Увести код у вікні редактора коду.
10. Компіляція програми виконується командою Compile меню Build
11. Якщо у програмі відсутні помилки, то її можна запустити на виконання
командою Start with debugging або Start without debugging меню Debug.

14
1.4. Варіанти завдань
Усі користувачі розробляють програму за власним сценарієм відповідно до
наведених прикладів. Варіанти завдань для даної лабораторної роботи не приводяться. В
процесі виконання лабораторної роботи користувач повинен:
1. Увести з клавіатури і вивести на екран значення змінних різних типів згідно з
форматами даних (форматне введення-виведення) і без використання форматів.
Використати всі функції, що приведені у таблиці 1.2.
2. Визначити розбіжності у використанні функцій введення - виведення.
3. За даними, що введені з клавіатури в оперативну пам’ять, визначити значення
виразу, використовуючи математичні функції, і вивести результат на екран. Вираз вибрати
згідно з варіантом по таблиці 1.7. Значення змінних A,B,C,D задати самостійно.
Таблиця 1.7. Арифметичні вирази

1 X=(2A - B2)/(D(SinC - 4.5)) 15. X=((1 - A)CeA)/((1-B)CosD)

2 X=(2.3 + AB2)/(0.4 + CeD) 16. X=(ACosA(1 + B3))/(C(1 - D2))

3. X=(-2.25(A + 2BC))/(B - D1/2) 17. X=A/(1 + B/(C + Ln(D + A)))

4. X=2ASin(B/2) + DC1/2 18. X=(CosA + SinB)/(LnC + LnD)1/2

5. X=(A - |B/C|)/(2.75Sin2D) 19. X=(ACos2B + 1)1/2LnC/D

6 X=(|A - B|2C2)/(1 - D2) 20. X=Arctg(4A/(B2C) - 1)1/2

7. X=e((SinA + SinB)/(C + D)) 21. X=A2 + |SinB/(C - D)1/2|

8. X=(1 - A)/(1 + A)+|(B - 2D)/C2| 22. X=(|A| + |B|)2/(D - C1/2)

9. X=(A2-B2)(C-D)/(e(A2 - B2))1/2 23. X=(A1/2 + B2)eC+D/(|A| - |B|)

10. X=(1-B)/(1+B)+ |(C-2A)/C2| 24. X=1/2Ln((1+SinA)/(1- SinB)2)

11. X=Sin3ACos2B/(eC + 1 + SinD) 25. X=Sin3CCos2A/(eA + 1 + SinB)

12. X=|1-B||1-A|/((1+SinC)(1+CosC))1/2 26. X=(1/(A2-B2)1/2)+(3C3/(C2-D2)1/2)

13. X=(ASinB+BCosA)/(1-SinC*|B+D|) 27. X=(eACos(B/2+D/C))/(DC+SinC)

14. X=A2/|1-B|+B2/|1-D|+C2/LnA 28. X=(A-4B)2/(1+(1+SinC)(1+CosC))

1.5 Контрольні запитання


1. Як визначаються коментарі у програмному коді?
2. Яка різниця між введенням даних з консолі та із стандартного вхідного потоку?
3. Яка різниця між виведенням даних на консоль та у стандартний вихідний
потік?
4. Які функції повертають значення EOF при неуспішному виконання операцій
введення та виведення?
5. Які функції можуть виконувати операції перетворення типів даних?
6. Які функції використовують форматний ввід та вивід? Як кодуються формати
введення та виведення?

15
7. Які заголовні файли використовуються для визначення функцій введення та
виведення даних?
8. Як і для чого виконується очищення буферу клавіатури?
9. Як можна вводити дані без відображення їх на екрані?
10. Які операції використовуються для введення та виведення даних за допомогою
об’єктів класів потоків?

16
Розгалужені обчислювальні процеси
Лабораторна робота 2
Мета роботи.
– вивчити особливості розгалужених обчислювальних процесів
– опанувати технологію використання логічних операторів
2.1 Теоретичні відомості
Алгоритмічна конструкція, що дозволяє виконавцеві алгоритму вибрати ту чи іншу
послідовність дій залежно від певних умов, називається розгалуженням або конструкцією
вибору альтернатив.
2.1.1. Вибір із двох альтернатив
Алгоритмічна конструкція альтернативного розгалуження, або конструкція вибору
з двох альтернатив, дозволяє виконавцеві алгоритму вибрати один із двох варіантів дій
залежно від істинності деякої умови. У мовах С/C++ альтернативні розгалуження
реалізуються умовним оператором (оператором розгалуження) і умовним виразом.
Синтаксис умовного оператора є таким:
if (< умова >)< оператор1;> [else <оператор2;>]
Тут if, else — зарезервовані слова, <умова> — довільний логічний вираз;
<оператор1;> і <оператор2;> — довільні оператори.
Виконання умовного оператора починається з обчислення значення булевого
виразу <умова>. Якщо цей вираз є істинним, то виконується < оператор1> і керування
передається наступному за умовним оператору (< оператор2> пропускається). Якщо вираз
<умова> є хибним, то <оператор1> пропускається, а виконується лише <оператор2> і на
цьому дія умовного оператора вважається завершеною.
Оерація «?:» дозволяє записати умовний вираз аналогічний умовному оператору:
< вираз1 > ? < вираз2 > :< вираз3 >;
Якщо < вираз1 > приймає істинне значення, то обчислюється < вираз2 >, інакше –
<вираз3 >.
Наприклад, умовний вираз для визначення абсолютного значення числа х можна
записати так: x > 0 ? abs= x : abs = -x;
2.1.2. Вкладеність конструкцій вибору
Гілки деякого розгалуження можуть містити інші розгалуження. Синтаксис
відповідного фрагменту C-програми такий:
іf (<умова1>) <оператор1;>
else if (<умова2>) <оператор2;>
else <оператор3;>
Піраміди вкладених розгалужень завжди можуть бути реалізовані послідовними
операторами розгалуження за рахунок ускладнення умов:
іf (<умова1>) <оператор1;>
if (!(<умова1>) && <умова2>) <оператор2;>
if (!(<умова1>) && !(<умова2>)) <оператор3;>
Але слід зазначити, що вкладені умовні оператори працюють значно швидше, ніж
серія умовних операторів у скороченій формі.
2.1.3. Операторний блок
Операторний блок, або складений оператор, — це послідовність операторів, що
оточені фігурними дужками { }. Синтаксис операторного блоку має такий вигляд:
{ <оператор1;>
...
<оператор2;>
}

17
2.1.4. Поліваріантний вибір
У мовах С/С++ алгоритмічну конструкцію поліваріантного виразу реалізовано
оператором перемикання. Наведемо його синтаксис:
switch ( < селектор > )
{ case <список констант1>: <оператор1;> break;
case <список констант2>: <оператор2;> break;
....................................
default: <операторN;> break;
}
Тут switch, case, default, break — це зарезервовані слова, <селектор> — змінна або
вираз, який має довільний перелічуваний тип; <список констант> — перелік розділених
комами значень того самого типу, що і селектор; <оператор> — будь-який оператор; дужки
«{» та «}» означують початок та кінць тіла оператора switch.
Оператор перемикання виконується за таким алгоритмом. Спочатку обчислюється
значення виразу-селектора. Потім вибирається той список констант, до якого належить
отримане значення, виконується відповідний оператор і на цьому дія оператора switch
завершується. Якщо поточне значення селектора не збігається з жодною з констант
перемикання, то виконується гілка default, а якщо її немає, то виконання оператора
перемикання завершується завдяки наявності оператора переривання break у кожній гілці
case.
2.2. Приклади програм
Приклад 2.1.
Обчислити значення функції y(b, c, x):

//ex2_1.cpp. Вкладені розгалуження


#include<iostream> //файл для операцій введення та виведення
#include<math.h> //заголовний файл для математичних функцій
using namespace std; //простір стандартних імен
int main() //ex3_1 обчислення функції
{
float y,b,c,x; //змінні для результату та вхідних даних
cout<<"define y: "<<endl; //умова задачі
cout<<"y=b*x+c, if x<=-4"<<endl;
cout<<"y=b*sqr(x), if (x<4)and(x>-4)"<<endl;
cout<<"y=b*x/c, if (x>-4)and(c<>0)"<<endl;
cout<<"y=1, if(c=0)and(x>4)"<<endl;
cout<<"input variables b,c,x: ";
cin>>b>>c>>x; //увести дані для розрахунків
if (x<=-4) y=b*x+c; //обчислити перший вираз
else if (x<4 && x>-4) y=b*pow(x,2); //обчислити третій вираз
else if (c!=0) y=b*x/c; //обчислити другий вираз
else y=1;
cout<<" b= "<<b<< " c= "<<c<<" x ="<<x<<endl;
cout<<"rezult : y= "<<y<<endl; //вивести результат
} //кінець програми

18
Рис.2.3. Результати роботи програми ex2_1.
Вкладені розгалуження
Приклад 2.2
Знайти розв’язки квадратного рівняння ax2 + bx + c = 0, коефіцієнти якого є
дійсними числами, що їх вводить користувач. Залежно від значень коефіцієнтів a, b, c та
дискримінанта d = b2  4ac можливі такі результати: всі дійсні числа є коренями (a = 0, b =
0, c = 0), коренів немає (a = 0, b = 0, c  0), є один корінь (a = 0, b  0), є два різних
дійсних корені (a  0, d > 0), два дійсних корені збігаються (a  0, d = 0) або існує два
комплексно-спряжених корені (a  0, d < 0).
//ex2_2.cpp. Розв’язати квадратне рівняння
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
float a,b,c,d; //коефіцієнти квадратного рівняння та дискримінант
float x1,x2; //корені квадратного рівняння
cout<<"solution of quadratic equation"<<endl;
cout<<"enter koefficients: a,b,c"<<endl;
cin>>a>>b>>c; //ввести значення коефіцієнтів
if (a!=0)
{
d=pow(b,2)-4*a*c; //обчислити дискримінант
if (d>0)
{
x1=(-b+sqrt(d))/(2*a); //розрахувати корені рівняння
x2=(-b-sqrt(d))/(2*a);
cout<<"x1= "<<x1<<" x2= "<<x2<<endl;
}
else
if (d==0)
cout<<"roots are equal: x= "<<-b/(2*a)<<endl;
else
cout<<"complex roots"<<endl; //дискримінант < 0
} //кінець гілки a!=0
else //а==0
if (b!=0)
cout<<"x= "<<-c/b<<endl; //лінійне рівняння
else
if (c!=0) //рівняння типу "ненульове число = 0"
cout<<"no roots"<<endl;
else cout<<"аll real numbers are the roots"<<endl;
//рівняння типу 0 = 0
} //кінець програми

19
Рис. 2.4. Результати роботи програми ex2_2.
Приклад 2.3
Запрограмуємо калькулятор, що виконує чотири арифметичні дії над дійсними
числами. Користувач вводить із клавіатури символ операції та значення операндів, а
програма повинна обчислити результат арифметичної дії.
//ex3_3.cpp. Калькулятор
#include<iostream>
#include<math.h>
using namespace std;
int main(){
char operation; //cимвол арифметичної операції
float result,operand1,operand2; //результат операції, операнди
bool flag; //ознака некоректного символу операції
cout<<"calculator "<<endl; //введення даних
cout<<"enter operand1 : "; cin>>operand1;
cout<<"enter operation + - * / : "; cin>>operation;
cout<<"enter operand2 : "; cin>>operand2;
flag=true;
switch (operation) //aналіз символу арифметичної операції
{ //виконання арифметичних дій
case '*': result=operand1*operand2; break;
case '+': result=operand1+operand2; break;
case '-': result=operand1-operand2; break;
case '/': if (operand2!=0) //запобігання діленню на нуль
result=operand1/operand2;
else{
cout<<"division by zero"<<endl;
flag=false; //ознака помилки
}
break;
default:
flag=false; //уведено помилковий символ операції
cout<<"invalid operation"<<endl;
break;
} //кінець оператора switch
//виведення результату
if (flag!=false) cout<<"result= "<<result<<endl;
else cout<<"result not defined"<<endl;
} //кінець програми

Рис. 2.5. Результати роботи програми ex2_3.


Калькулятор

20
2.3. Варіанти завдань

13.
1.

14.
2.

3.

15.

4. 16.

5.
17.

6. 18.

7.
19.

20.
8.

9. 21.

10. 22.

21
23. Визначити умови взаємного
11. розташування двох прямих, що задаються
коефіцієнтами рівнянь вигляду ax + by + c =
0 (паралельні, перпендикулярні,
перетиняються, збігаються)
24. Визначити тип трикутника за
значеннями уведених його сторін
12. (рівнобедрений, рівнобокій, прямокутний,
різнобокій, не існує).

2.4 Контрольні запитання


1. Як формується складена умова, що об’єднує декілька простих умов?
2. Наведіть синтаксис оператора одноальтернативного розгалуження.
3. До яких типів даних не може належати значення виразу-селектора в операторі
вибору?
4. Яка структура працює ефективніше: вкладені оператори if...else чи серія
операторів if? Відповідь обґрунтуйте.
5. Чи можна перервати роботу програми за допомогою оператора break?
6. Чому в гілках оператора switch слід використовувати оператор break?
7. Що таке умовний вираз і як він записується?
8. Що працює ефективніше: умовний вираз чи оператор if...else?

22
Циклічні обчислювальні процеси
Лабораторна робота 3
Мета роботи.
– вивчити особливості циклічних обчислювальних процесів
– опанувати технологію використання операторів циклів
– навчитися розробляти алгоритми та програми циклічних процесів
3.1 Теоретичні відомості
Алгоритмічна конструкція, що дозволяє виконавцеві алгоритму повторювати певну
послідовність дій задану кількість разів, називається конструкцією повторення або
циклічною. Кожне виконання операторів тіла циклу супроводжується перевіркою умови
повторення циклу і називається його ітерацією. Якщо умова повторення істинна, то тіло
циклу виконується ще раз, якщо хибна, то виконання циклу припиняється і здійснюється
перехід до виконання наступного за циклом оператора. Змінні, значення яких
модифікуються в тілі циклу і впливають на істинність умови повторення, називаються
параметрами циклу. Виконанню будь-якого циклу має передувати ініціалізація його
параметрів. У мовах С/С++ є три різновиди операторів циклу: оператор циклу з
передумовою, оператор циклу з постумовою та оператор циклу з лічильником
3.1.1. Цикл із передумовою
У циклі з передумовою перша перевірка умови продовження циклу відбувається
ще до першого виконання його тіла. Це означає, що за деяких значень параметрів циклу
його тіло може не виконатися жодного разу. Цей тип циклу застосовують лише у тому
випадку, коли кількість повторень є невідомою до початку виконання циклу Синтаксис
оператора циклу з передумовою:
while (<умова продовження циклу>)
<оператор>;
Тут while (<умова продовження циклу>) є заголовком циклу, <оператор> — його тілом.
Тіло циклу може бути операторним блоком і містити в собі будь-які оператори: циклу,
вибору, присвоєння тощо. Умова продовження циклу повинна бути виразом булевого
типу.
3.1.2. Цикл із постумовою
Як і цикл із передумовою, цикл із постумовою застосовують тоді, коли кількість
ітерацій циклу є невідомою до початку його виконання. Умова продовження циклу з
постумовою записується після тіла циклу та вперше перевіряється після виконання
операторів тіла. Цикл з постумовою за будь-яких обставин буде виконано принаймні один
раз. Синтаксис оператора циклу з постумовою такий:
do { <оператор1;> ... <операторN;> } while ( <умова повторення
циклу> );
Тут do, while — зарезервовані слова, <оператор1>;...<операторN>; — тіло циклу;
<умова повторення циклу> — деякий булів вираз.
3.1.3. Цикл із лічильником
Відстежити істинність умови повторення циклу дозволяє спеціальний різновид
параметра циклу, лічильник ітерацій. Лічильник — це змінна, що під час кожного
повторення збільшується на одиницю. В операторі циклу з лічильником облік числа
виконаних ітерацій вказується у заголовку, і тому цей оператор є зручною формою запису
циклів із наперед визначеною кількістю повторень. Синтаксис оператора циклу з
лічильником такий.
for ([<вираз1>]; [<вираз2>];[<вираз3>] )
<оператор;>

23
Тут for — зарезервоване слово («для»); <вираз1> ініціалізує лічильник та
виконується один раз на початку циклу; <вираз2> — деякий булів вираз, котрий визначає
умову повторення циклу; <вираз3> змінює значення лічильника циклу, найчастіше це
просто операція інкремента чи декремента; <оператор> — простий або складений
оператор, що є тілом циклу. Фраза for() є заголовком циклу, а зазначений після круглих
дужок оператор — тілом циклу. Найчастіше <вираз1> записують у вигляді
<лічильник>=<початкове значення>; <вираз2> є виразом відношення (<, >, <=, >=, !=, ==), в
якому порівнюються поточне та кінцеве значення лічильника. Початкове та кінцеве
значення лічильника — це вирази того самого перелічуваного типу; лічильник — це
змінна перелічуваного типу, що є узгодженим за присвоюванням з типом початкового та
кінцевого значення.
3.1.4. Переривання та продовження циклу
У деяких програмах виникає потреба завершити цикл або його ітерацію
передчасно. У мовах С/С++ цього ефекту можна досягти, використовуючи оператори break
та continue.
Передчасний вихід із циклу означає, що умова повторення циклу під час виходу з
нього є істинною. Для примусового переривання циклу слід виконати оператор break.
Оператор continue здійснює пропуск усіх інструкцій, записаних після його виклику в тілі
циклу. Таким чином, після виконання оператора continue завжди перевіряється умова
продовження циклу.
Якщо використовуються вкладені цикли, то оператор break перериває той цикл, у
якому він виконується. Після переривання внутрішнього циклу управління передається
заголовку зовнішнього циклу для перевірки умови його продовження. Аналогічно працює
і оператор continue: його виконання забезпечує дії нової ітерації того циклу, в якому цей
оператор здійснено.
3.2. Приклад алгоритму та програми
Обчислити суму ряду, елемент котрого розраховується за формулою
5 
(1) k 1 x 2 k 1
  (2k  1)(2k  1)!
x 1 k 0

//ex3.1
#include<iostream>
#include<iomanip>
#include<math.h>
using namespace std;
float x; //параметр зовнішньої суми
float k=0; //параметр внутрішньої суми
float sum=0;//сума ряду
float error; //точність розрахунків
float member; //елемент ряду
//=======обчислення факторіала числа=========
float factorial(int number)
{ //параметр number– число, факторіал котрого розраховується
float fact=1;
if (number==0) fact=1;
else
{
for(int i=1;i<=number;i++)
fact*=i;
}
return (float)fact;

24
}
///===========виведення поточних розрахунків===========
void OutputSum()
{
cout<<setw(5)<<x<<setw(10)<<k<<setw(20)<<member<<setw(15)<<sum<<
endl;
}
//===========обчислення елемента ряду та суми==============
void MemberAndSum()
{
double Numerator; //чисельник елемента ряду
double Denominator; //знаменник елемента ряду
for (x=1;x<=5;x++)
{
k=0;
do
{
Numerator=pow(x,(2*k-1));
if(k>16) //floating point error - overflow
{
cout<<"overflow - break cycle with k"<<endl;
break;
}
else
{
Denominator=(2*k-1)*factorial(2*k+1);
member=(float)Numerator/Denominator;
member*=(-1);
sum+=member;
OutputSum();
k++;
}
}while(fabs(member)<error); //поки не досягнуто
// заданої точності
}
}
/////// головна функція////////////
int main()
{
cout<<"To calculate the sum of row "<<endl;
cout<<" 5 endlessness "<<endl;
cout<<" sum ( sum (((-1)^(k+1))*(x^(2k-1))/((2k-1)(2k+1)!)))"
<<endl;
cout<<" x=1 k=0"<<endl;
cout<<"input error: ";
cin>>error;
cout<<"result of iterations"<<endl;
cout<<"=================================================="<<endl;
cout<<" x k member sum "<<endl;
cout<<"=================================================="<<endl;
MemberAndSum();
cout<<"=================================================="<<endl;
cout<<"sum="<<sum<<endl;
system("pause");
}

25
Рис. 3.1. Результати роботи програми ex3.1
3.3. Варіанти завдань

5 
(1) k 1 x 2 k 1 5 
(1) k x 4 k 1
1.   12.  
x 1 k  0 ( 2k  1) k! x 1 k 0 ( 2k )!( 4k  1)

5 
(1) k ( x / 2) 2 k 1
2.   13.
x 1 k 0 (k  1)k!

5 
(1) k 1 x 2 k 1 5 
(1) k 1 ( x / 3) 2 k 1
3.   14.  
x 1 k  0 ( 2k  1) k! x 1 k 0 (2k  1)!
5 
(1) k x 2 k 1 5 
(1) k (k  1) x k
4.   15.  
x 1 k 0 ( k  x)! k! x 1 k 0 k!

26
5 
(1) k x k  2 5 
(1) k x k
5.   16.   (k  2) 3
x 1 k 0 ( k  1)(k  2)! x 1 k 0 k


5
(1) k x 2 k
6.  k x (k  1)(k  2)
17.
x 1 k 0

 18.
5
(1) k x 2 k
7.  k x (k  1)(k  2)
x 1 k 0

5 
(1) k ( x  1) k 1 5 
(1) k x k
8.  (k  1)(k  2)...(k  x)
19.   (k  2) 3 k
x 1 k 0 x 1 k 0

9.
20.


5
(1) k x  1
10.   21.
x 1 k 0 (1  x k ) 2

11. 22.

3.4 Контрольні запитання

1. У чому полягає відмінність між циклами з передумовою та циклами з


постумовою?
2. Якому типу даних може належати лічильник у циклі for?
3. Яке значення має лічильник після завершення циклу for?
4. Що може спричинити «зациклення» програми?
5. За яких умов цикли while та for не виконаються жодного разу?
6. Коли цикл виконується лише один раз?
7. У чому полягає відмінність між такими операторами циклів, як for, while, do …
while?
8. Поясність алгоритм роботи вкладених циклів.
9. Якщо оператор break розміщується у внутрішньому циклі, то який цикл він
перериває?
10. За яких умов слід обирати цикли for та while?

27
Цикли з розгалуженням
Лабораторна робота 4
Мета роботи.
– вивчити особливості циклічних обчислювальних процесів з розгалуженнями
– опанувати технологію рекурентних обчислень
– навчитися розробляти алгоритми та програми розвинення функцій у ряди
4.1 Теоретичні відомості
4.1.1. Рекурентні співвідношення
Формула, що виражає член послідовності через один або декілька попередніх,
називається рекурентним співвідношенням. Послідовність, члени якої задовольняють
деякому рекурентному співвідношенню, називається рекурентною.
У загальному випадку рекурентне співвідношення визначає залежність члена
послідовності {Sn} від k попередніх: Sn = F(Sn–k, ..., Sn–1).
Наближене значення суми ряду можна отримати або обмежуючись сумою перших
n його членів, або обчислюючи суму з наперед заданою точністю. Формула загального
члена даного ряду є достатньо простою, але використовувати її не раціонально, оскільки
для кожного члена ряду треба обчислювати степінь і факторіал. Набагато вищої
ефективності можна досягти, обчислюючи член ряду за допомогою рекурентного
співвідношення. Найпростішими прикладами рекурентних послідовностей є арифметична
та геометрична прогресії, елементи яких пов’язані з попередніми елементами
співвідношеннями an = an–1 + d та an = an–1 · q, де d та q — деякі сталі величини, an –
значення елемента ряду на кроці n.
Із заданою точністю може бути обчислена сума лише збіжного ряду, а довільний
степеневий ряд має певну область збіжності (можливо, порожню), тобто збігається не за
всіх, а лише за деяких значень x (ряд, що розглядається нами як приклад, збігається для
будь-якого дійсного x). По-друге, простий спосіб перевірки точності часткової суми ряду
існує не для всіх рядів. Такий спосіб існує, зокрема, для знакопереміжних рядів,
абсолютні величини членів яких, починаючи з деякого номера, утворюють монотонно
спадну послідовність. Для таких рядів сума всіх членів, починаючи від (n+1)-го, є меншою
за модулем від n-го

4.1.2. Функції користувача


Функція користувача містить оператори, що логічно не залежать від іншого коду
програми, і може викликатися з будь-якого місця програми довільну кількість разів.
Формат функції визначає її заголовок та тіло, яке містить оператори відповідно до
алгоритму. Визначення функції передбачає наявність заголовка та тіла. Функцію без
заданого прототипу визначають перед функціями, які її викликають, а ту, що має
прототип, можна визначати в будь-якому місці програми. Функція має повернути тільки
одне визначене значення до основної програми. Тип значення, що повертається,
визначається у заголовку функції.
Оголошення функції (прототип) задається у вигляді:

тип_значення_що_повертається ім'я_функції (тип_параметра


ім'я_параметра1, тип_параметра ім'я_параметра2);

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


визначенні збігаються. Не ставиться символ ; наприкінці заголовка. Для повернення
значення з функції в тілі функції необхідно мати оператор повернення return.
28
Приклад визначення найбільшого з двох чисел:

float max(float a,float b) //заголовок функції з параметрами


{
float m; //найбільше значення
m =(a>b)?a:b; //умовний вираз
return m; //значення, що визначилося та повертається
}
Функцію можна оголосити у вигляді:

void ім'я_функції(void);

Тип void значення, що повертається, означає, що така функція не повертає ніякого


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

ім'я_функції(аргументи);

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

ім'я_змінної = ім'я_функції(аргументи);

Для виконання лабораторної роботи необхідно використовувати ряди, які


представляють функції (табл. 4.1).

Таблиця 4.1 Рекурентні формули розвинення функцій у ряди

Функції Розвинення у ряд Тейлора


sin(x) x - x3/3! + x5/5! - x7/7! +...
cos(x) 1 - x 2/2! + x4/4! - x6 /6! +...
arctg(x) x - x3/3 + x5/5 - x7/7 +...
ln (x) (x-1) - (x-1)2/2 + (x-1)3/3 - (x-1)4/4+...
ex 1 + x / 1! + x2 / 2! + x3 / 3! + ...
e-x 1 - x/1! + x2/2! - x3/3! + x4/4!-...
sh (x) x + x3/3! + x5/5! + x7/7! +...
x1/2 y0=1, yn+1 = 1/2*(yn+x/yn), n = 0, 1, 2,…

4.2. Приклад алгоритму та програми

29
Обчислити значення у, розвинувши функцію е х у ряд Тейлора, де x змінюється від
-5 до 5 з кроком 1.

Алгоритм задачі
1. Увести початкове, кінцеве значення аргументу функції та його крок зміни.
2. Повторювати дії:
2.1. Задати поточне значення аргументу функції, що дорівнює початковому
значенню;
2.2. Якщо поточне значення аргументу не більше за кінцеве, то виконати такі дії:
2.2.1. Якщо аргумент функції знаходиться в межах від -2 до +2, то визначити
значення функції за стандартною функцією та за формулою ряду Тейлора, виконавши дії:
2.2.1.1. Визначити початкову суму ряду, що дорівнює 1;
2.2.1.2. Задати точність розрахунків поточного елемента ряду;
2.2.1.3. Задати початкову кількість елементів ряду, що дорівнює 1.
2.2.1.4. Поки значення поточного елемента ряду більше за значення точності
розрахунків повторювати такі дії:
– визначити значення елемента ряду;
– додати значення елемента ряду до суми;
– перейти до наступного елемента ряду.
2.2.2. Визначити похибку.
2.2.3. Якщо аргумент функції менший за -2, то визначити значення функції за
формулою ряду Тейлора, стандартною функцією та похибку.
2.2.4. Якщо функцію не визначено при заданих значеннях аргументу, то задати
значення 1 для ознаки невизначеності функції, вивести відповідне повідомлення, інакше
вивести значення функції та похибку.
2.3. Змінити поточне значення аргументу функції.
2.4. Перейти до дій п. 2.2.
3. Кінець повторень

Код програми
// |e^x - e^x/2, if -2 ≤ x ≤ 2
// Y={
// |e^(x+3)+1, if x < -2
// x between -5, 5, step 1
//e^x=1 + x / 1! + x2 / 2! + x3 / 3! + ...
#include <stdio.h> //підключення бібліотек уведення-виведення
#include <conio.h>
#include <math.h> //підключення бібліотек математичних функцій

float y, //вираз за формулою Тейлора


st, //значення стандартної функції exp()
x, //аргумент функції
xn, xk, //початкове, кінцеве значення аргументу
xs, err, //крок зміни аргументу та похибка
t; //точність розрахунків
bool flag=true; // прапорець для визначення можливості
//розрахунку функції
//////// обчислення експоненти за формулою Тейлора /////////
double expon(float a)
{ //e^a=1 + a^1 / 1! + a^2 / 2! + a^3 / 3! + ...
//параметр a - аргумент функції e^a
float sum=1; //сума членів ряду

30
int i=1; //знаменник елемента ряду
float member=1; //поточний елемент ряду
while (member>t) //поки поточний елемент перевищує
{ //точність розрахунків
member*= a/i; //поточний елемент за
// формулою Тейлора
sum+=member; //накопичення суми
i++;
} //перехід до нового елемента ряду
return sum; //повернення значення експоненти з функції
}
/////////////////// основна функція //////////////////////
int main (void)
{
puts("lab4: calculation exponention function");
printf("\n input xn, xk, xs (-5 5 1)\n");
scanf("%f%f%f", &xn, &xk, &xs);
printf("\n input t \n");
scanf("%f", &t);
puts("===================================================");
printf(" x y standart error \n");
puts("===================================================");
for ( x=xn;x<=xk;x+=xs) //цикл перебору значень аргументів функції
{ if (x>=-2&&x<=2) //перевірка умов вибору
{ //розрахункової функції
y=expon(x)-expon(x/2); //визначення функції за
// формулою Тейлора
st=exp(x)-exp(x/2); //визначення функції за
//стандартною формулою
err=fabs(st - y); //розбіжності між точним і
//наближеним значеннями функції
}
else if (x<-2)
{
y=expon(x+3)+1;
st=exp(x+3)+1;
err=fabs(st-y);
}
else if (x>2) flag =false; // функцію не визначено
if ( flag) //якщо функцію визначено, то вивести
// її значення
printf (" %f %f %f %f \n", x, y, st, err);
else printf (" %f not define \n", x );
//функцію не визначено
}
getch();
}

31
Рис. 4.1. Результати роботи програми ex4.1
4.3. Варіанти завдань
1. Обчислити значення функції у, розвинувши функцію cos(x) у ряд Тейлора.
Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

2. Обчислити значення функції у, розвинувши функцію у ряд Тейлора. Аргумент х


змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

3. Обчислити значення функції у, розвинувши функцію е-х у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

4. Обчислити значення функції у, розвинувши функцію sin(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

5. Обчислити значення функції у, розвинувши функцію ln(x) у ряд Тейлора.


Аргумент х змінюється від -1 до 3 з кроком 0.5. Визначити похибку.

32
6. Обчислити значення функції у, розвинувши функцію arctg(x) у ряд Тейлора.
Аргумент х змінюється від 0 до 3 з кроком 0.5. Визначити похибку.

7. Обчислити значення функції у, розвинувши функцію sh(x) у ряд Тейлора.


Аргумент х змінюється від 0 до 3 з кроком 0.5. Визначити похибку.

8. Обчислити значення функції у, розвинувши функцію e x у ряд Тейлора. Аргумент


х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

9. Обчислити значення функції у, розвинувши функцію ln(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

10. Обчислити значення функції у, розвинувши функцію sin(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

11. Обчислити значення функції у, розвинувши функцію cos(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

12. Обчислити значення функції у, розвинувши функцію e -x у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку .

.
13.Обчислити значення функції у, розвинувши функцію у ряд Тейлора. Аргумент х
змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

33
14. Обчислити значення функції у, розвинувши функцію tg(x) у ряд Тейлора.
Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.

15. Обчислити значення функції у, розвинувши функцію cos(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 3 з кроком 0.5. Визначити похибку.

16. Обчислити значення функції у, розвинувши функцію sin(x) у ряд Тейлора.


Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.

.17. Обчислити значення функції у, розвинувши функцію tg(x) у ряд Тейлора.


Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.

18. Обчислити значення функції у, розвинувши функцію sh(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

19. Обчислити значення функції у, розвинувши функцію cos(x) у ряд Тейлора.


Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.

20. Обчислити значення функції у, розвинувши функцію sh(x) у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку.

21. Обчислити значення функції у, розвинувши функцію e -x у ряд Тейлора.


Аргумент х змінюється від -2 до 2 з кроком 0.5. Визначити похибку .

23. Обчислити значення функції у, розвинувши функцію tg(x) у ряд Тейлора.


Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.

34
24. Обчислити значення функції у, розвинувши функцію ln(x) у ряд Тейлора.
Аргумент х змінюється від -2 до 4 з кроком 0.5. Визначити похибку.

25. Обчислити значення виразу, використавши ряди для визначення констант pi та


е: pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 -… ; e = 1 + 1/1! + 1/2! + 1/3! +….
Визначити похибку обчислень.

4.4 Контрольні запитання


1. Що таке ітераційний цикл?
2. Які причини зациклювання програм?
3. За яких умов цикл не виконується?
4. У чому полягають особливості застосування операторів break та continue?
5. Яке призначення функцій С++? Яка роль функції main()?
6. Що таке прототип функції? Що таке визначення функції?
7. Дати поняття рекурсивних функцій. Технологія припинення рекурсивного
виклику.
8. Чим пряма рекурсія відрізняється від непрямої?
9. Якими бувають оператори виклику функцій?
10. Як викликається функція, що повертає значення void?
11. Як викликається функція, що повертає значення будь-якого типу, який
відрізняється від типу void?
12. Значення якого типу повертає функція, якщо тип не вказано?
13. Скільки значень може повернути функція?

35
Рекурсивні функції
Лабораторна робота 5
Мета роботи.
 вивчити особливості рекурсивних процесів
 опанувати технологію рекурсивних обчислень
 навчитися розробляти алгоритми та програми із застосуванням
рекурсивних функцій
5.1 Теоретичні відомості
Означення називається рекурсивним, якщо воно задає елементи множини за
допомогою інших елементів цієї самої множини. Об' єкти, що задані рекурсивним
означенням, також називаються рекурсивними. Під терміном "рекурсивно задана функція"
розуміється така функція, значення якої для данноrо apгумента обчислюється за
допомогою значень для попередніх apгументов. При кожній конкретній реалізації процес
обчислення такої функції задається рекурентною послідовністю. У практиці обчислень це
пов'язано з тим, що, маючи справу з реальною функцією, ми не обчислюємо її в реальному
завданні на усій числовій осі, а обчислюємо для деякої кінцевої послідовності значень
apгументов.
Рекурсія — це такий спосіб організації обчислювального процесу, за якого функція
звертається сама до себе. Такі звернення називаються рекурсивними викликами, а функція,
що містить рекурсивні виклики, — рекурсивною.
Перед тим, як записати рекурсивну функцію будь-якою мовою програмування,
необхідно записати рекурентне співвідношення, що визначає метод обчислення функцій.
Рекурентне співвідношення повинне містити як мінімум дві умови:
 умову продовження рекурсії (крок рекурсії);
 умову закінчення рекурсії.
Розглянемо функцію , де аргумент є цілим додатним числом, таким, що
або . Потрібно обчислити значення членів послідовності Рекурсивне
завдання послідовності як послідовності значень функції включає такі два етапи.
1. Функція задається безпосередньо у вигляді числових значень для деякої
конечної множини початкових значень аргументу .
2. Задається метод або формула, які дозволяють, знаючи усі значення функції
при , обчислити її значення при , тобто знайти .
В результаті отримуємо peкуррентні співвідношення, що описують рекурсивно
задану функцію , рівносильну послідовності .
Отриманий запис цих двох етапів

називається рекурентним співвідношенням.


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

36
Програмний код, що реалізує рекурсивні обчислення, такий:
int Fib(int n)
{
if (n == 0) return 0;
else if (n == 1) return 1;
else return Fib(n–1)+Fib(n–2);
}

5.2. Приклад алгоритму та програми


Одним із найпростіших прикладів рекурсії – це функція обчислення факторіала.
Нагадаємо, що факторіалом n! натурального числа n називається добуток усіх цілих чисел
від одиниці до n. Вважають також, що 0!=1. Обчислення факторіала зводиться до
багаторазового застосування рекурентної формули n! = (n  1)!· n. Ця формула є
рекурсивною, оскільки означує «факторіал через факторіал». Рекурсивне обчислення n!
низхідним: «обчислити (n – 1)! і отримане значення помножити на n». При обчисленні
(n – 1)! застосоване те саме правило: «обчислити (n – 2)! і отримане значення помножити
на n – 1». Рекурсія являє нескінченний цикл, для її переривання необхідно визначити
умову завершення рекурсії. Такою умовою буде рівність n нулеві.
Повне рекурсивне означення факторіала:

//ex4_9.cpp. Обчислення факторіала числа


#include<iostream>
using namespace std;
int x; //число, факторіал якого необхідно обчислити
int Factorial(int n) //оголошення функції
{
if (n==0) return 1;
else return Factorial(n-1)*n; //рекурсивний виклик функції
}
int main() //головна функція
{
cout<<"calculate factorial"<<endl;
cout<<"Enter x "<<endl;
cin>>x;
cout<<"x!="<<Factorial(x)<<endl;
system("pause");
}

5.3. Варіанти завдань


1. Знайти суму цифр натурального числа n та значення глибини рекурсії,
використовуючи рекурентне означення функції f(n):

Підказка. Умова продовження рекурсії: сума цифр числа дорівнює останній цифрі
плюс сума цифр числа без останньої цифри (числа, що ділиться без остачі на 10). Умова
закінчення рекурсії: якщо число дорівнює 0, то сума його цифр дорівнює 0.
2. Знайти кількість одиниць в двійковому представленні числа n та значення
глибини рекурсії, використовуючи рекурентне означення функції f(n) (& - операція
побітового логічного множення):

37
3. Знайти значення біноміального коефіцієнта при заданих n, k за формулою:

= ,

використовуючи рекурентне співвідношення:

Визначити глибину рекурсії.


4. Знайти значення функції Аккермана A(m, n), використовуючи рекурентне
співвідношення:

Визначити глибину рекурсії.


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

6. По колу стоять людей, яким присвоєні номери від 1 до . Починаючи відлік з


першого і рухаючись по колу, кожна друга людина виходитиме з кола доти, поки не
залишиться одна. Нехай номер того, хто залишився, . Потім по колу стоятиме людей і
процедура виходу з колу людей повторюватиметься доти, поки не залишиться одна
людина з номером . Ці процедури повторюватимуться доти, поки номер тої людини, що
залишиться, не стане рівним первинній кількості людей в потоковому раунді. Визначити
кількість повторень процедури виходу людей з кола після першої ітерації та номер
людини, яка залишилася.
Підказка. Використати рекурсію, визначивши рекурентне співвідношення:

7. Визначити рекурсивні функції зображення натурального числа у двійковій,


вісімковій системах числення та у системі числення з основою N > 1 та глибину рекурсії.
Числа у десятковій системі числення вводити з клавіатури.
8. Визначити рекурсивну функцію обчислення найбільшого спільного дільника
НСД{п,т) натуральних чисел, яка ґрунтується на співвідношенні НСД(п,т) = НСД(т,r), де
r -залишок від ділення п на т.
9. Визначена рекурсивна функцію через рекурентне співвідношення:

38
Визначити глибину рекурсії та обчислити функції за заданими значеннями
:

10. Визначити рекурсивну функцію обчислення степеня дійсного числа з цілим


показником , згідно з рекурентним співвідношенням:

11. Коефіцієнти розкладання бінома (a+b)i, тобто біноміальні коефіцієнти,


утворюють і-й рядок трикутника Паскаля. Кожне число в трикутнику, крім перших трьох,
є сумою чисел, розташованих над ним у попередньому рядку. Число в i-му рядку (i = 0, 1,
2, …) на j-му місці (j = 0, 1, …, i), задається формулою . «Верхівка»
трикутника має наступний вигляд.

Надрукувати перші рядків трикутника Паскаля із заданою кількістю рядків,


використавши рекурсивне визначення його елементів.
12. Написати рекурсивну функцію, яка методом ділення відрізання навпіл
(методом дихотомії) знаходить з точністю корінь рівняння на
відрізку [ a , b ] ( eps  0, a  b , f ( a )  f (b )  0 ). Згідно з методом дихотомії, якщо i
мають різні знаки, то між точками існує корінь . Нехай – середня точка в інтервалі
. Якщо f (m)  0 , то корінь x  m . Якщо f (m)  0 , то або f (a ) і f (m) мають різні
знаки, або f (m) і f (b) мають різні знаки. Якщо f (a )  f (m)  0 , то корінь лежить в
інтервалі a  x  m Інакше він лежить в інтервалі m  x  b Процес продовжується доти,
поки інтервал не стане менший eps . Визначити глибину рекурсії під час обчислення
кореня рівняння.
13. Реалізувати генератор послідовності псевдовипадкових чисел {Vi} на основі
рекурентного співвідношення Vi = (aVi–1 + bVi–2 + c) mod m, де a, b, c, m — довільні
натуральні параметри. Перші два значення, V1 і V2, задаються випадково. Підібрати
значення параметрів, за яких послідовність є схожою на випадкову.
14. Довести, що для перших чисел послідовності Фібоначчі
справедлива формула: ,

де - біноміальні коефіцієнти, що розраховуються за рекурентним співвідношенням:

Числа Фібоначчі визначаються рекурентним співвідношенням:

39
15. Для числа, що введено з клавіатури, визначити рекурсивні функції для
обчислення суми та кількості його цифр, максимальної та мінімальної цифри. Визначити
рекурентні співвідношення та глибину рекурсії.
16. Задати з клавіатури перший член і різницю арифметичної прогресії. Визначити
рекурсивні функції для знаходження -го члена арифметичної прогресії та суми її
членів. Визначити рекурентні співвідношення та глибину рекурсії.
17. Задати з клавіатури перший член і знаменник геометричної прогресії.
Визначити рекурсивні функції для знаходження -го члена геометричної прогресії та суми
її членів. Визначити рекурентні співвідношення та глибину рекурсії.
18. Визначити добуток двох комплексних чисел . Вхідні
значення – числа . Результат – числа . Використати рекурсивний алгоритм
Карацуби.
Підказка. З алгоритмом Карацуби початкові операнди множення подаються
як вирази , де для 32-бітних процесорів,
визначається як половина розміру (в 32-бітових словах) мінімального по довжині
множника. Таким чином, початкові множники розбиваються на молодшу і старшу частині.
Після розбиття операндів виконується розрахунок проміжних значень:

Результуючий добуток розраховується за формулою:

Множення на здійснюється за допомогою зсуву, а підсумовування та за


допомогою конкатенації. Метод Карацуби дозволяє звести операцію множення двох
великих чисел до трьох множень чисел половинного розміру (в порівнянні з початковими
операндами), п'яти операцій підсумовування і одного зсуву.
19. Потрібно сплатити поштове відправлення, вартість котрого складає копійок,
а в наявності тільки поштові марки номіналом копійок. Скількома різними
способами можна сплатити поштове відправлення? Розробити рекурсивну функцію для
обчислення кількості зображень числа у вигляді суми певних фіксованих чисел з
використанням рекурентних співвідношень.
Підказка. Використати рекурентне співвідношення для чисел Фібоначчі.
20. Довести, що рекурсивна послідовність

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

, де

40
- залишок від ділення на 10.
22. Двійкові числа довжини складаються з нулів і одиниць. Нехай –
функція, значенням якої є кількість двійкових чисел довжини , що не містять двох або
більше одиниць поспіль. Визначити рекурентне співвідношення, яке задає функцію ,
надрукувати такі числа, підрахувати їх кількість.
23. По заданим b, p, m обчислити значення виразу . Обчислення
виконати, використовуючи алгоритм, що базується на двійковому розкладанні показника
степені p:

24. Функція f визначена так:

Обчислити значення , якщо

5.4 Контрольні запитання


1. Що таке рекурсивне визначення і рекурсивний об’єкт?
2. Визначити поняття рекурсії. Що таке рекурсивна підпрограма?
3. Як визначається глибина рекурсії?
4. Як обмежити послідовність вкладених викликів рекурсивної підпрограми?
5. Коли рекурсія неефективна і коли її необхідно уникати?
6. Чим викликається переповнення стеку під час рекурсії?

41
Покажчики
Лабораторна робота 6
Мета роботи.
 ознайомитися з особливостями посилальних типів даних;
 опанувати технологію застосування посилальних типів даних;
 навчитися розробляти алгоритми та програми із застосуванням
посилальних типів даних.
6.1 Теоретичні відомості
6.1.1. Основні поняття
До посилальних типів відносяться покажчики та посилання. Покажчики
дозволяють працювати з адресами комірок оперативної пам’яті, тим самим вони
реалізують непрямий доступ до їх вмісту. Посилання є альтернативними іменами змінних.
Застосування покажчиків і посилань як параметрів функцій дозволяє функції змінювати
значення своїх аргументів, отже, повертати в програму більше ніж одне значення.
Змінні, що зберігають адреси інших змінних, називаються змінними-покажчиками
чи просто покажчиками. Для визначення адреси змінної означена операція & отримання
адреси. Якщо оголошена та ініціалізована змінна, наприклад, int value=10, її адресу можна
визначити виразом &value. Якщо значення, що зберігаються, займатимуть послідовність
байтів, покажчик адресує перший байт цієї послідовності.
6.1.2. Оголошення та ініціалізація
Константні значення, арифметичні вирази та регістрові змінні не зберігають
значення в оперативній пам’яті, тому застосувати до них операцію & неприпустимо.
Змінну-покажчик оголошують:
<тип>* <ідентифікатор_покажчика>;
Тут <тип> — простий чи структурований тип адресованої змінної; <ідентифікатор_-
покажчика> — рядок символів, що є ім’ям змінної-покажчика; символ * означає «вказати
на».
Покажчик перед використанням iнiцiалiзується адресою змінної або значенням
іншого покажчика. Покажчику можна присвоїти значення 0 ( NULL). Такий покажчик не
адресує жодну змінну.
Посилання є псевдонімом змінної, тобто її альтернативним іменем і для нього не
резервується місце в оперативній пам’яті. Синтаксис оголошення посилання застосовує
символ &, який записують після типу змінної:
<тип>& <ідентифікатор_посилання >;
Посилання слід iнiцiалiзувати ім’ям змінної. Типи посилання та змінної, значенням
якої ініціалізуються посилання, мають збігатися.
6.1.3. Операції над покажчиками
Для покажчиків означені операції адресування, присвоєння, арифметичні та
відношення.
Унарна операція & повертає адресу свого аргументу.
Значення змінної за певною адресою отримують, застосувавши операцію
розименування. Операція позначається символом *, який записують перед іменем
покажчика. Операція * повертає об’єкт, на який вказує покажчик.
Операція присвоєння використовується для надання значення покажчику
Арифметичні операції: унарні операції інкремента та декремента, бінарні операції
додавання та віднімання цілого числа, віднімання одного покажчика з іншого.
Покажчики одного типу можна порівнювати один з одним. При цьому
порівнюються адреси, що зберігаються в покажчиках.

42
Покажчик на функцію містить адресу її в оперативній пам’яті. Ім’я функції — це
початкова адреса її коду. До функцій можна застосувати тільки дві операції: виклик і
отримання її адреси, тобто визначити її покажчик.
Синтаксис оголошення покажчика на функцію:
<тип> (*<ідентифікатор покажчика>)(<оголошення параметрів>);
Щоб викликати функцію через покажчик, його слід розименувати.
Існують три способи передачі аргументів у функцію — як значення, як посилання
та як покажчики. Щоб повертати з функцій більше одного значення, слід передати функції
аргументи-посилання або аргументи-покажчики. Під час оголошення функції параметри-
посилання вказують у її заголовку, використовуючи операцію посилання &. Параметри-
покажчики оголошують в заголовку функції, використовуючи операцію непрямої
адресації *.
В операціях виклику функції з аргументом-покажчиком застосовується операція &
адресації змінної, значення котрої змінюватимуться. В операції виклику функції з
параметром-посилання аргументом є ім’я змінної.
6.1.4. Методи розв’язанні нелінійних рівнянь
Метод перебору. При розв’язанні нелінійного рівняння методом перебору
задаються початкове значення аргументу x=a і крок h, який при цьому визначає і точність
знаходження коріння нелінійного рівняння. Поки виконується умова F(x)*F(x+h)>0
аргумент x збільшуємо на крок h (x=x+h). Якщо добуток F(x)*F(x+h) стає від’ємним , то
на інтервалі [x, x+h] існує розв’язок рівняння.
Метод половинного ділення. При розв’язанні нелінійного рівняння методом
половинного ділення задаються інтервал [a, b], на якому існує тільки одне рішення, і
бажана точність ε. Потім визначається середина інтервалу с=(а+b)/2 і перевіряється умова
F(a)∙F(c)<0. Якщо вказана умова виконується, то праву межу інтервалу b переносимо в
середню точку с (b=c). Якщо умова не виконується, то в середню точку переносимо ліву
межу(a=c). Ділення відрізку навпіл триває доки |b - a|>ε. .
Метод хорд. При розв’язанні нелінійного рівняння методом хорд задаються
інтервал [a, b], на якому існує тільки одне рішення, і точність ε. Потім через дві точки з
координатами (a, F(a)) і (b, F(b)) проводимо відрізок прямої лінії (хорду) і визначаємо
точку перетину цієї лінії з віссю абсцис (точка c). Якщо при цьому F(a)∙F(c)<0, то праву
межу інтервалу переносимо в точку с (b=c). Якщо вказана умова не виконується, то в
точку c переноситься ліва межа інтервалу (а=с). Пошук рішення припиняється, коли
досягається задана точність |F(c)|< ε. Для визначення точки перетину хорди з віссю абсцис
використовується формула .
Метод дотичних. При розв’язанні нелінійного рівняння методом дотичних
задаються початкове значення аргументу x0 і точність ε. Потім в точці(x0, F(x0))
проводимо дотичну до графіка F(x) і визначаємо точку перетину дотичної з віссю абсцис
x1. У точці (x1, F(x1)) знову будуємо дотичну, знаходимо наступне наближення шуканого
рішення x2 і так далі. Вказану процедуру повторюємо доки |F(xi)|> ε. Для визначення

точки перетину (i+1) дотичної з віссю абсцис використовується формула

Умова збіжності методу дотичних .


6.2. Приклад алгоритму та програми
Знайти корені нелінійного рівняння виду . Пошук наближеного значення
хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснюватимемо методом ділення
відрізка навпіл. Для цього обчислимо середину m відрізка, і якщо f(m)0, то пошук
продовжуватимемо на тому з відрізків [a; m], [m; b], на кінцях якого функція приймає

43
значення різних знаків. Реалізація алгоритму подана у програмі ex5_5. Для обчислення
значення функції в заданій точці визначимо функцію f(xx). У програмі змінюватимуться
значення змінних через розименування покажчика, наприклад, *a = x, де double* const a —
константний покажчик на тип double, double x — змінна, на яку посилатиметься покажчик.
Спроба змінити сам покажчик приведе до синтаксичної помилки.
//ex6_1.срр пошук кореня рівняння методом ділення відрізка навпіл
#include<iostream>
#include<math.h>
using namespace std;
double precision=0.00001,x; //точність та аргумент функції
//========== обчислити значення функції в точці ===============
double f(double *param)
{
if (*param==0) //перевірити точку розриву,
*param+=precision; //перейти до наступної точки
return exp(*param)-1/(*param);//значення функції в поточній точці

}
//=====реалізація алгоритму половинного ділення ================
void solution(double* a, double* b )
{ //параметри - константні покажчики на границі відрізка
do{
x=(*a+*b)/2; //визначити середину відрізка
if (f(&x)*f(&(*a))<0) //знаки функції різні на кінцях відрізка
*b=x; //вибрати новий кінець відрізку
else *a=x;
}while( (*b-*a)>=precision); //точність розрахунків досягнута
}

//======================= головна функція =====================


int main(){
double left,right; //границі відрізка
cout<<"pointer to data"<<endl;
cout<<"define root of e^x=1/x"<<endl;
cout<<"input a,b"<<endl;
cin>>left>>right; //ввести значення кінців відрізка
double* pl=&left;//ініціалізувати константні покажчики
double* pr=&right;
solution(pl,pr); //розв’язати рівняння
cout<<"root = "<<x<<endl; //вивести значення кореня рівняння
system("pause");
}

Рис. 6.1. Результат роботи програми ex6_1.


Розв’язання нелінійного рівняння

44
6.3. Варіанти завдань
1. Надрукувати таблиці значень функцій cox(x) та ex на відрізку [a; b] із кроком h,
розвинувши функції у ряд Тейлора та використавши покажчики на функції. Для довідки:
ряд Тейлора для функції сos(x) =1 – x 2/2! + x4/4! – x6 /6! +..., ряд Тейлора для функції e x=1
+ x / 1! + x2 / 2! + x3 / 3! + ...
2. Розрахувати біноміальні коефіцієнти: C(m, n) = 1, якщо m  1, n = 0 або n = m;
C(m, n) = C(m – 1, n – 1) + C(m – 1, n) в протилежному випадку. Значення n та m
передавати у функцію як покажчики на тип int.
3. Нехай в трикутнику ABC задані координати вершин A=(0,0), B=(а,b), де а і b –
цілі числа, що вводяться користувачем. Розробити функцію, яка визначає такі координати
вершини C=(x,y), щоб площа трикутника ABC була мінімальною (не рівною нулю).
Координати вершин передавати у функцію як покажчики на тип int.
4. Вивести в порядку зростання всі звичайні нескоротні дроби в діапазоні від 0 до
1, знаменники яких не перевищують 15. Чисельники та знаменники дробів подати як
покажчики на типи int
5. Написати програму, яка здійснює введення у вільному форматі одного цілого
числа і його переведення з текстового представлення в значення типу int. Функція getint()
повинна повертати значення отриманого числа через параметр або сигналізувати
значенням , якщо вхідний потік вичерпаний. Значення EOF повертати через оператор
return. Знаки - або +, за якими не йде цифра, функція розуміє як неправильне
представлення числа.
6. Розв’язати нелінійне рівняння x=cos(x) методами перебору та хорд, визначивши
інтервал [a, b], на якому існує рішення рівняння. Порівняти результати розв’язків двома
методами. У функції, що реалізують алгоритми, передавати покажчики на тип float.
7. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
перебору та дотичних. У функції, що реалізують алгоритми, передавати покажчики на тип
float.
8. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
перебору та хорд.У функції, що реалізують алгоритми, передавати покажчики на тип float.
9. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
перебору та хорд. У функції, що реалізують алгоритми, передавати покажчики на тип
float.
10. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
перебору та хорд. У функції, що реалізують алгоритми, передавати покажчики на тип float
11. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
дотичних та хорд. У функції, що реалізують алгоритми, передавати покажчики на тип float
12. Знайти корені нелінійного рівняння виду . Пошук наближеного
значення хоча б одного кореня рівняння f(x) = 0 на відрізку [a; b] здійснювати методами
дотичних та ділення навпіл. У функції, що реалізують алгоритми, передавати покажчики
на тип float
13. Використовуючи покажчики на функції для їх викликів, знайти найбільше,
найменше та середнє арифметичне значення двох чисел, які генеруються комп’ютером.

45
14. Використовуючи покажчики на функції для їх викликів, обчислити

ланцюговий дріб

15. Використовуючи покажчики на функції для їх викликів, обчислити

ланцюговий дріб

16. Використовуючи покажчики на функції для їх викликів, обчислити

ланцюговий дріб

17. Скласти програму обчислення найбільшого числа Фібоначчі, яке не перевищує


число та номера найменшого числа Фібоначчі, яке більше від числа . Використати
функції, що повертають покажчики на тип int.
18. Число називається досконалим, якщо воно дорівнює сумі всіх своїх дільників,
крім самого цього числа. Використати функцію, що повертає покажчик на тип int, в якому
зберігається досконале число з проміжку [2,n]. Надрукувати досконалі числа з проміжку
[2,n], котрі є повними квадратами.
19. Скласти програму для знаходження всіх простих чисел із діапазону [2, n], які є
числами послідовності Фібоначчі або числами виду , де q – ціле число. Для
обчислення простих чисел використати функцію, яка повертає значення типу покажчик на
цілий тип та приймає покажчики.
20. Послідовність задана рекурентним співвідношенням

Для знаходження найбільшого члена цієї послідовності та його номера, який не


перевищує число а, використати функцію, що повертає покажчики на типи int знайдених
значень.
21. Скласти програму обчислення числа  за формулою Грегорі
та за формулою Валліса ,
використовуючи покажчики для повернення значень з функцій обчислення числа .
Розрахувати кількість ітерацій в каждому з методів.
22. Задати натральне число . Визначити, чи можна його подати у вигляді суми
квадратів двох натуральних чисел. Якщо можливо, то визначити вказати пару таких
натуральних чисел, що . Використати функції, що повертають покажчики на
цілий тип та використовують покажчики як параметри.
23. Задати натуральне число . Знайти усі менші за паліндроми, які при
піднесенні до квадрата дають також паліндром. Число є паліндромом, якщо його можна
прочитати справа наліво та зліва направо однаково, наприклад, 12321.Використати
функції, що повертають покажчики на цілий тип та використовують покажчики як
параметри.
24. Скласти програму визначення чисел Армстронга, що складаються з двох, трьох
та чотирьох цифр. Натуральне число із цифр є числом Армстронга, якщо сума його
цифр, піднесених до го степеня, дорівнює самому числу, наприклад, 153=13+53+33.

46
Використати функції, що повертають покажчики на цілий тип та використовують
покажчики як параметри.

6.4 Контрольні запитання


1. Дати поняття посилальних типів даних?
2. Як здійснюється до доступ до значення змінної?
3. Як оголосити покажчик на певний тип та посилання на змінну?
4. Як ініціалізувати покажчик та посилання?
5. Що відбувається під час звернення до неініціалізованого покажчика?
6. Які значення можна присвоювати покажчику?
7. Які операції припустимі для покажчиків?
8. Що таке «розименування покажчика»?
9. Як змінюється значення покажчика при додаванні чи відніманні цілого числа?
10. У чому полягає особливість покажчиків типу void*?
11. Як використовують покажчики на функції?

47
Одновимірні масиви
Лабораторна робота 7
Мета роботи.
 ознайомитися з особливостями типу масиву;
 опанувати технологію застосування масивів даних;
 навчитися розробляти алгоритми та програми із застосуванням
одновимірних масивів
7.1 Теоретичні відомості
Тип масиву — це структурований тип даних, множина допустимих значень котрого
складається з усіх масивів, для яких зафіксовано:
– розмірність;
– базовий тип;
– індексний тип;
– множину значень індексу.
З точки зору математики одновимірний масив — це вектор. Змінну, що матиме тип
масиву, можна оголосити з використанням такого синтаксису:
<тип елементів> <ім’я масиву> [<кількість елементів>];
Основні властивості масивів:
– однорідність — усі елементи належать одному типу;
– сталість — вимірність масиву задається під час його оголошення і не змінюється
протягом роботи з ним;
– рівнодоступність — спосіб доступу до всіх елементів є однаковим;
– послідовність розташування — усі елементи масиву розташовані в послідовних
комірках оперативної пам’яті;
– індексованість — елементи однозначно ідентифікуються своїми індексами;
– упорядкованість індексу — індексний тип має бути простим порядковим типом
даних.
Базовими операціями обробки масивів є:
– введення та виведення масиву;
– ініціалізація масиву;
– копіювання масиву;
– пошук максимального або мінімального елемента;
– обчислення узагальнювальних характеристик (сум елементів, їх добутків);
– пошук заданого елемента;
– перестановка елементів або обмін значеннями між елементами масиву;
– вставка та видалення елемента.
Базові операції обробки масивів зручно реалізовувати у вигляді функцій, що згодом
можуть бути використані як «архітектурні блоки» при розв’язанні більш складних задач.
//ввести масив
for( i=0;i<n;i++)
cin>>mas[i];
cout<<"Entered array"<<endl;

//вивести масив
for( i=0;i<n;i++)
cout<<mas[i]<<" ";
cout<<endl;

48
//генерація масиву
srand((unsigned)time( NULL )); //ініціалізація генератора
//випадкових чисел
for(i=0;i<n;++i) //генерація псевдовипадкових чисел в діапазоні
mas[i]=rand()%30; //від 0 до 29

// пошук максимального елемента


max=mark[0]; //максимальної
for(i=1;i<n;i++) //пошук мінімальної та максимальної оцінок
{
if (max<mark[i]) max=mark[i]; //модифікація
//поточного максимуму
}
//бульбашкове сортування
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if (mas[i]>mas[j])
{
tmp=mas[i];
mas[i]=mas[j];
mas[j]=tmp;
}

7.2. Приклад алгоритму та програми


Скласти програму сортування масиву методом вибору.
Алгоритм програми
1 Вибрати перший елемент невідсортованої частини масиву і вважати його
мінімальним; запам’ятати індекс цього елемента.
2 Для елементів від наступного після вибраного і до останнього повторювати такі
дії:
2.1 Порівняти вибраний елемент і поточний.
2.2 Якщо вибраний елемент більший за поточний, запам’ятати поточний
елемент як мінімальний, а його індекс — як індекс мінімального елемента.
2.3 Поміняти місцями мінімальний і вибраний на кроці 1 елементи.
2.4 Пересунути початок невідсортованої частини на одну позицію вправо.
Код програми
//ex7_9.cpp. Сортування методом вибору
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int n; //кількість елементів
int a[10]; //масив, що сортується
//=================== генерація масиву =======================
void input()
{
srand((unsigned)(time(NULL))); //ініціалізувати генератор
//випадкових чисел
cout<<"enter number of the components (<=10)"<<endl;
cin>>n; //ввести кількість елементів массиву
for(int i=0;i<n;i++) //генерувати масив
a[i]=rand()%30;
}

49
//============= виведення масиву =======================
void output()
{
for (int i=0;i<n;i++) //вивести проміжні результати
cout<<a[i]<<" ";
cout<<endl;
}
//==============сортування масиву вибором ==================
void sort()
{
int min,imin; //мінімальний елемент і його індекс
for(int i=0;i<n-1;++i)
{
min=a[i]; //пошук мінімального елемента в діапазоні від
//i-го до останнього елемента
imin=i; //індекс мінімального елемента
for (int j=i+1;j<n;j++) //пошук мінімального елемента
if (min>a[j])
{
min=a[j];
imin=j;
}
a[imin]=a[i]; //обмін місцями мінімального та поточного
//елементів
a[i]=min;
output(); //вивести проміжні результати
}
}
//=============== головна функція =============================
int main()
{
cout<<"selection sort"<<endl;
input(); //генерувати масив
cout<<"generated array"<<endl;
output(); //вивести масив
cout<<"series of selection "<<endl;
sort(); //сортувати масив
cout<<"sorted array "<<endl;
output(); //вивести відсортований масив
system("pause");
}

Рис. 7.1. Результати роботи програми сортування масиву методом вибору

50
7.3. Варіанти завдань
1. Створити одновимірний массив, кількість елементів якого задана
користувачем. У масиві поміняти місцями максимальний і мінімальний елементи.
Надрукувати вхідний та вихідний масиви.
2. Створити одновимірний массив, кількість елементів якого задана
користувачем. Упорядкувати масив у порядку зростання, підрахувати кількість
переставлень елементів та їх порівнянь. Надрукувати вхідний та вихідний масив.
3. Заданий одновимірний масив А, кількість елементів якого задана
користувачем. Побудувати масив В, кожний елемент якого обчислюється за формулою
, де - максимальний елемент масиву А. Надрукувати вхідний та вихідний
масиви.
4. Задані одновимірні масиви А, В з 10 чисел. Побудувати масив С, кожний
елемент якого обчислюється за формулою:

В масиві С поміняти максимальний елемент і перший. Вивести масиви до


переставлення елементів та після.
5. Створити одновимірний массив, кількість елементів якого задана
користувачем. Визначити максимальне та мінімальне значення серед елементів із парними
та непарними номерами.
6. Створити одновимірний массив, кількість елементів якого задана
користувачем.
Обчислити суму елементів між максимальним та мінімальними значеннями масиву.
7. Створити два одновимірних массивів, кількість елементів яких задана
користувачем. Здійснити обмін значень двох векторів та визначити їх скалярний добуток.
8. Створити два одновимірних массивів, кількість елементів яких задана
користувачем. Знайти найменший серед тих елементів першого вектора, які співпадають
із значеннями елементів другого вектора.
9. Заданий масив цілих чисел. Побудувати новий масив, в якому спочатку стоять
числа, що діляться на 2, потім ті, що діляться на 2 та 3, потім на 3. Надрукувати вхідний та
вихідний масиви.
10. Згенерувати значення елементів одновимірного масиву за допомогою
генератора псевдовипадкових чисел, задавши кількість елементів масиву з клавіатури.
Знайти мінімальний за значенням елемент і записати його на початок масиву,
вивільнивши для нього місце шляхом зсуву елементів масиву вправо.
11. Створити масив, значеннями елементів якого є коефіцієнти многочлена
. Знайти значення многочлена при заданому аргументу ,
похідної від многочлена при заданому та інтегралу від многочлена на
заданому відрізку.
12. Ввести значення елементів одновимірного масиву, задавши попередньо їх
кількість. Визначити кількість входжень до масиву значення кожного з його елементів.
13. В одновимірному масиві обчислити кількість елементів у найдовшій серії.
Серія — це послідовність однакових елементів, розташованих поряд.
14. Згенерувати додатні та від’ємні псевдовипадкові значення елементів
одновимірного масиву, ввівши кількість елементів з клавіатури. Переставити елементи
масиву так, щоб спочатку були розташовані всі додатні елементи, потім всі від’ємні.
Порядок серед додатних і від’ємних елементів має зберегтися.
15. У введеному з клавіатури одновимірному масиві знайти найбільший серед
від’ємних та найменший серед додатних елементів масиву.
51
16. Побудувати одновимірний масив, значення елементів якого є числами
Фібоначчі. Числа Фібоначчі формуються за правилом: кожне наступне число дорівнює
сумі двох попередніх.
17. Задати два упорядкованих за зростанням одновимірних масиви. Побудувати
упорядкований за зростанням третій масив злиттям двох заданих.
18. У селищі, де N будинків, розташованих уздовж прямої дороги з однієї сторони
на рівних відстанях, прокладають телефонний зв’язок. Зазначено, скільки телефонних
апаратів треба встановити в кожному будинку. Кожен телефон має бути з’єднаний з АТС
окремим кабелем. Визначити, в якому будинку необхідно встановити АТС, щоб сумарна
довжина кабелів була мінімальною.
19. Задані масиви А, В з цілих чисел, кількість вводиться з клавіатури.
Побудувати масив С, в якому кожний елемент дорівнює найбільшому спільному дільнику
чисел аі, bі. Використати алгоритм Евкліда.
20. Створити одновимірний массив, кількість елементів якого задана
користувачем. Знайти максимальний серед парних елементів та мінімальний серед
елементів з парними індексами. В масиві поміняти місцями знайдені максимальний та
мінімальний елементи, надрукувати вхідний та вихідний масиви.
21. Створити одновимірний массив, кількість елементів якого задана
користувачем. Впорядкувати масив за алгоритмами сортування вставкою (включенням),
сортування вибором, сортування обміном (бульбашкове сортування). Визначити
покажчики ефективності кожного з алгоритмів.
22. Створити одновимірний массив, кількість елементів якого задана
користувачем. Значення елементів в масиві можуть повторюватися. Визначити індекс
першого та останнього входження заданого числа в масив. Знайти число, яке
повторюється найбільшу кількість разів.
23. Створити одновимірний массив, кількість елементів якого задана
користувачем. Знайти суму елементів з парними індексами, добуток від’ємних елементів,
максимальний елемент та його індекс серед додатних чисел, мінімальний елемент та його
індекс серед елементів зх непарними індексами.
24. Обчислити суму та добуток двох многочленів:
та

7.4 Контрольні запитання


1. Дати означення масиву та типу масиву.
2. Якими є властивості масивів даних?
3. Яким є принцип зображення масиву в оперативній пам’яті?
4. Як здійснюється доступ до елементів одновимірного масиву?
5. Чи може список ініціалізації масиву містити більше (менше) значень, ніж
вказано в оголошенні масиву?
6. Які базові операції обробки одновимірних масивів?
7. Чим відрізняються методи сортування масивів?
8. Приведить найшвидший та найповільніший алгоритми сортування масивів.
9. Чим відрізняються алгоритми пошуку в упорядкованому та неупорядкованому
масивах?
10. Як повернути масив із функції?
11. Що означає подвійний покажчик на одновимірний масив?

52
Багатовимірні масиви
Лабораторна робота 8
8.1 Теоретичні відомості
8.1.1. Оголошення багатовимірних масивів. Доступ до елементів
Синтаксис оголошення змінної матричного типу в мовах С/C++:
<тип елементів> <ім’я матриці> [<кількість рядків>][<кількість
стовпців>];
У цьому оголошенні <тип елементів> — будь- який тип даних, окрім файлового
типу; <ім’я матриці> — деякий ідентифікатор; <кількість рядків> і <кількість стовпців> —
константи, що визначає розмірність матриці. Межі діапазону допустимих значень індексів
рядків і стовпців визначаються значеннями від 0 до <кількість рядків>–1 та від 0 до
<кількість стовпців>–1. Масиви, що мають більш ніж два виміри, оголошуються в
аналогічний спосіб.
Доступ до елементів матриці здійснюється операцією індексування [] за двома
індексами, які визначають номер рядка та номер стовпця елемента. Синтаксис операції
індексування є таким:
<ім’я масиву>[<номер рядка>][<номер стовпця>]

8.1.2. Базові операції обробки двовимірних масивів


Перелік базових операцій над матрицями та їх елементами:
– створення нової матриці за заданим алгоритмом;
– введення та виведення матриць;
– пошук елементів матриці за певним критерієм;
– визначення, чи задовольняє матриця або окремі її елементи певній властивості;
– виконання певних операцій над компонентами матриць (переставлення рядків і
стовпців, множення матриць тощо).
Введення матриці:
int a[5][5];
int main(){
for(int i=0;i<5;i++) //зовнішній цикл по рядках
for(int j=0;j<5;j++) //внутрішній цикл по стовпцях
cin>>a[i][j]; //із клавіатури елементи
} //вводяться через символ пробілу
Під час виведення матриці переводити курсор на новий рядок слід лише після
виведення всіх елементів поточного рядка:
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
cout<<a[i][j]<<" "; //вивести елементи рядка
cout<<endl; //перевести курсор на новий рядок
}
Ініціалізація елементів матриці деякими значеннями:
int a[5][5];
int main(){
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
a[i][j]=10; // альтернативи: a[i][j]=rand()%20;
// a[i][j]=i*j; тощо
}
Пошук значення та індексів максимального елемента матриці:
max=a[0][0]; //початкове значення максимального елемента
for( int i=0;i<n;i++)

53
for( int j=0;j<n;j++)
if ( max < a[i][j])
{
max=a[i][j]; //запам’ятати максимальний елемент
imax=i; //та його індекси
jmax=j;
}
Перестановка рядків або стовпців
for(i=0;i<n;i++) //цикл по рядках
{
tmp=a[i][0]; //альтернатива для цілих значень:
a[i][0]=a[i][4]; //a[i][4]^=a[i][0]^=a[i][4]^=a[i][0];
a[i][4]=tmp;
}

8.2. Приклад алгоритму та програми


Скласти програму множення двох матриць.
Добутком матриці A та матриці B називається матриця С, елемент якої cij дорівнює
скалярному добутку i-го вектор-рядка матриці А та j-го вектор-стовпця матриці B. Це
означення можна записати у вигляді рівності C = AB, де
n
ci j  ai  b j   aik  bkj , i  1..m, j  1..l , k  1..n
T

k 1

//ex7_16.cpp. Множення матриць


#include<iostream>
using namespace std;
typedef float Matrix[10][10]; //тип матриці
int i,j; //індекси елементів
Matrix A,B; //вхідні матриці
Matrix C; //матриця результату множення
int row1,row2; //кількість рядків вхідних матриць
int col1,col2; //кількість стовпців вхідних матриць
//=================== функція введення матриці ===============
void input(Matrix Mas,int& line, int& kol)
{
//Mas — покажчик на матрицю, яку вводять
//line,kol — кількість рядків і стовпців
do{
cout<<"input numbers of rows >=1 ";
cin>>line;
cout<<"input numbers of columns >=1 ";
cin>>kol;
if ((line<1) || (kol<1)) //контроль правильності введення
cout<<"it''s few, input more"<<endl;
}
while ((line<=1)&& (kol<=1)); //перевірка коректності даних
cout<<"input matrix:"<<endl;
for(int i=0;i<line;i++)
for( int j=0;j<kol;j++)
cin>>Mas[i][j];
}

54
//=========== процедура виведення матриці ====================
void output(Matrix Mas,int line, int kol)
{ //Mas — покажчик на матрицю
//line,kol — кількість рядків і стовпців
for(int i=0;i<line;i++) //вивести елементи матриці
{
for(int j=0;j<kol;j++)
cout<<Mas[i][j]<<" "; //вивести елементи рядка
cout<<endl; //перевести курсор на новий рядок
}
}
//================== множення матриць ========================
void mult()
{ //використовуються глобальні змінні A,B,C
int k; //індекс елемента скалярного добутку векторів
if (col1!=row2) //перевірка відповідності матриць
cout<<"multiplication is impossible — matrix are
unconformable"<<endl;
else
{
for (int i=0;i<row1;i++) //вибрати i-й вектор-рядок
for(int j=0;j<col2;j++) //вибрати j-й вектор-стовпець
{
C[i][j]=0;
for (k=0;k<col1;k++)
C[i][j]=C[i][j]+A[i][k]*B[k][j]; //скалярне множення
//векторів
}
}
}
//================== головна функція ==========================
int main(){
cout<<"input matrix A: "<<endl;
input(A,row1,col1); //ввести матрицю А
cout<<"input matrix B: "<<endl;
input(B,row2,col2); //ввести матрицю В
cout<<"matrix A :"<<endl;
output(A,row1,col1); //вивести матрицю А
cout<<"matrix B :"<<endl;
output(B,row2,col2); //вивести матрицю В
mult(); //перемножити A та B
cout<<"result of multiplication :"<<endl;
output(C,row1,col2); //вивести матрицю C
system("pause");
}

55
Рис. 8.1. Результати роботи програми множення матриць
8.3. Варіанти завдань
1. У заданій квадратній матриці знайти суму значень елементів, що розташовані
на головній діагоналі або вище від неї і є більшими за всі елементи, розташовані нижче від
головної діагоналі.
2. У заданій квадратній матриці значення деяких діагональних елементів
дорівнюють нулю. Переставити рядки або стовпці матриці таким чином, щоб діагональні
елементи стали ненульовими. Якщо це неможливо зробити, вивести відповідне
повідомлення.
3. Задати квадратну матрицю, ввівши кількість рядків і стовпців з клавіатури.
Упорядкувати значення елементів головної діагоналі за алгоритмом вставки, а значення
побічної діагоналі — за алгоритмом обміну. Визначити кількість порівнянь та обмінів під
час сортування.
4. Здійснити обхід матриці по спіралі за годинниковою стрілкою, починаючи від
її лівого верхнього кута. Вивести елементи матриці у порядку їх обходу.
5. У селищі, де N будинків, розташованих уздовж прямої дороги з однієї сторони
на рівних відстанях, прокладають телефонний зв’язок. Зазначено, скільки телефонних
апаратів треба встановити в кожному будинку. Кожен телефон має бути з’єднаний з АТС
окремим кабелем. Визначити, в якому будинку необхідно встановити АТС, щоб сумарна
довжина кабелів була мінімальною.
6. Задана дійсна матриця poзмipy n*m, в якій не всі елементи дорівнюють нулю.
Одержати нову матрицю шляхом ділення вcix елементів заданої матриці на її найбільший
за модулем елемент. Замінити діагональні елементи матриці на найбільший за модулем
елемент.
7. Задана дійсна матриця розміру m*n. Знайти середнє арифметичне найбільшого
і найменшого значень її елементів. Поміняти місцями найбільше і найменше значення
елементів.
8. В заданій дійсній квадратній матриці вимірністю n*n, знайти суму елементів
рядка, в якому знаходиться елемент з найменшим значенням. Вважаємо, що такий елемент
єдиний.
9. Задана дійсна матриця вимірності m*n. Упорядкувати її рядки за неспадністю
суми елементів рядків. Вивести масив сум елементів рядків та матрицю.

56
10. В заданій дійсній матриці m*n переставити місцями рядок, що містить елемент
з найменшим значенням з рядком, що містить найбільше значення. Вважаємо, що ці
елементи єдині.
11. Задана дійсна матриця розміру n*m, всі елементи якої різні. В кожному рядку
вибираємо елемент з найменшим значенням, потім серед цих чисел вибираємо найбільше.
Вказати індекси елементу із знайденим значенням.
12. Задане натуральне число n, матриця цілих чисел А розміром 2*n. Знайти суму
тих її елементів з другого рядка, які мають в першому рядку рівні за значенням елементи.
13. Задана квадратна матриця цілих чисел розмірності n*n. Знайти найменше із
значень елементів стовпчика, який має найбільшу суму модулів елементів.
14. Задана дійсна квадратна матриця розмірністю n*n. В рядках з відємним
елементом на головній діагоналі знайти суму елементів, найбільший з усіх елементів та
його індекс.
15. Задана дійсна квадратна матриця розмірності n*n. Знайти суми тих елементів,
які розміщені відповідно нижче, вище та на головній діагоналі, в рядках, що починаються
з відємного елементу.
16. Визначити кількість особливих елементів мат риці та вивести їх значення та
індекси. Особливим елементом називається такий, що є більшим за суму інших елементів
свого стовпчика та в рядку зліва від нього розташовані менші за нього елементи, а справа
– більші.
17. Задати матрицю довільної вимірності та вектор. Визначити транспоновану
матрицю та здійснити множення матриці на вектор.
18. Для заданої цілочислової матриці визначити індекси та значення її сідлових
точок. Елемент матриці називається сідловою точкою, якщо він є найменшим у своєму
рядку та найбільшим у своєму стовпчику.
19. Для заданої матриці довільної вимірності визначити скалярний добуток рядка з
найбільшим елементом на стовпчик з найменшим елементом.
20. Задати матрицю розмірності mn (m, n  3). Починаючи з лівого нижнього кута
матриці та рухаючись лише праворуч і догори, досягти її правого верхнього кута і вибрати
при цьому такі значення елементів, що їх сума буде максимальною. Вивести перелік
вибраних елементів.
21. Знайти добуток довільної кількості матриць довільної розмірності. Кількість
матриць, які треба перемножити, їх розмірність і значення елементів задаються
користувачем.
22. Для заданої матриці та вектора довільної вимірності здійснити множення
матриці та вектор та вектора на матрицю.
23. Для заданої матриці довільної вимірності визначити вектор, -ий елемент
котрого дорівнюватиме 1, якщо елементи -го рядка матриці впорядковані за спаданням,
та 0, якщо -ий рядок матриці є симетричним.
24. В заданій матриці довільної вимірності обчислити суму елементів парних
рядків, найбільші значення у непарних рядках, середнє арифметичне серед від’ємних
елементів матриці та індекси нульових елементів.

8.4 Контрольні запитання


1. Дати означення матриці.
2. Як зображується матриця в оперативній пам’яті?
3. Як здійснити доступ до елементів масиву чи матриці?
4. Як здійснити доступ до елемента матриці, користуючись значенням тільки
одного індексу?
5. Означити типові операції над матрицями.

57
Обробка рядків
Лабораторна робота 9
9.1 Теоретичні відомості
9.1.1. Визначення рядка

Рядок - це масив символів, який закінчується символом кінця рядка ' \0'. Значенням
символа є ціле число, яке є кодом таблиці символів ASCII. Символ відображається у
одинарних лапках, наприклад: 'z'. Кожний символ в оперативній пам'яті займає один
байт. Рядок характеризується дов-жиною, яка дорівнює кількості символів, та обсягом
пам'яті. Обсяг пам'яті, який займає рядок, на одиницю більший за довжину рядка за
рахунок символа кінця рядка '\0'.
Кожний символ рядка має свій індекс. Доступ до символа рядка здійснюється за
допомогою операції [ ]. Рядок і всі його символи мають одне ім'я. При оголошенні рядка
задаються ім'я та кількість елементів рядка. Довжина рядка визначається читанням
символа кінця рядка '\0' під час введення рядка. Для позначення нового рядка
використовується символ '\n'.
Рядок доступний через покажчик (адресу) на перший символ у рядку. Таким чином,
ім'я рядка - це покажчик на перший символ.
Формати оголошення рядка:

char ім'я_рядка[кількість символів];


char *ім'я_рядка;

Рядок можна ініціалізувати у процесі оголошення через покажчик на


рядок.Приклад:
char string[50];
сhar * pointer="mastering Visual C++"; //покажчик на рядок

Рядкові (літеральні) константи на відміну від значення символа записуються у


подвійних лапках.
У процесі оголошення рядка як масиву символів останній повинний мати такий
розмір, щоб зберігати рядок і символ кінця рядка '\0'. Якщо рядок більший за масив
символів, то символи, які виходять за його межі, будуть змінювати дані, що знаходяться в
наступних за масивом комірках пам'яті.
Рядки можуть компонуватися у масив рядків та утворювати текст. Під час
оголошення масиву рядків необхідно визначити два індекси: кількість рядків і
максимальну кількість символів у одному рядку.
Приклад: char text[5][25];

Уведення та виведення рядка здійснюється за допомогою функцій puts(char* s);


gets(char *s); без використання циклів. Параметром функцій ведення та виведення є
покажчик на рядок. Якщо вводити рядки за допомогою класів потоків через операцію >>,
то символи рядка вводяться до першого символа пропуску. Символи рядка після символа
пропуску ігноруються.
Для рядків не визначені операції присвоєння (=) та порівняння (>, <, ==, !=). Для
виконання подібних дій використовуються відповідні функції, прототипи яких визначені у
файлі string.h. Перелік деяких функцій обробки рядків подано у табл. 4.1.

58
9.1.2. Деякі функції обробки рядків
Умовні позначення: destination - рядок призначення; source - початковий рядок;
maxlen - максимальна довжина рядка (підрядка); n - кількість символів; s, s1, s2 -
поточні рядки; с - символ для пошуку; endptr - помилка під час перетворення рядка;
radix - основа системи числення.
Таблиця 4.1 Прототипи функцій з файлу string.h
Назва Призначення Формат Значення, що повертається
strupr Перетворення char *strupr(char *s); Покажчик на змінений
малих літер на рядок
великі
strlwr Перетворення char *strlwr(char *s); Покажчик на змінений
великих літер на рядок
малі
strcpy Копіювання рядка char *stpcpy(char Покажчик на рядок-копію
*destination, const char
*source);
strncpy Копіювання char *strncpy(char Покажчик на рядок-копію
частини рядка *destination, const char
*source, size_t maxlen);
strlen Довжина рядка size_t strlen(const char *s); Кількість символів у рядку
без урахування символа '\0'
strcat Конкатенація char *strcat(char Покажчик на об’єднаний
рядків(об’єднання) *destination, const char рядок
*source);
strncat Додавання частини char *strncat(char Покажчик на об’єднаний
рядка до іншого *destination, const char рядок
рядка *source, size_t maxlen);
strtod Перетворення рядка double strtod(const char *s, Число типу double
у число типу double char **endptr);
strtol Перетворення рядка long strtol(const char *s, Число типу long
у число типу long char **endptr, int radix);
strrchr Пошук останнього char *strrchr(char *s, int c); Покажчик на останнє
входження заданого місцезнаходження заданого
символа символа
strstr Пошук першого char *strstr(char *s1, const Покажчик на перше
входження заданого char *s2); місцезнаходження заданого
підрядка символа
strcspn Пошук першого size_t strcspn(const char *s1, Довжина початкової ланки
сегмента, що не const char *s2); s1, яка не містить символи з
містить символів з рядка s2
заданого набору
символів
strcmpi Порівняння рядків int strcmpi(const char *s1, Значення 0, якщо рядки
без розбіжності у const char *s2); рівні, значення менше за 0,
регістрах літер якщо перший рядок менший
за другий, значення більше
за 0, якщо перший рядок
більший за другий
strcmp Порівняння рядків int strcmp(const char Значення 0, якщо рядки
*s1,const char *s2); рівні, значення менше за 0,
якщо перший рядок менший
за другий, значення більше
59
за 0, якщо перший рядок
більший за другий
strncmp Порівняння int strncmp(const char *s1, Значення 0, якщо рядки
частини рядка з const char *s2, size_t n); рівні, значення менше за 0,
частиною іншого якщо перший рядок менший
рядка за другий, значення більше
за 0, якщо перший рядок
більший за другий
strncmpi Порівняння частин int strncmpi(const char *s1, Значення 0, якщо рядки
рядків без const char *s2, size_t n); рівні, значення менше за 0,
розбіжності у якщо перший рядок менший
регістрах літер за другий, значення більше
за 0, якщо перший рядок
більший за другий
strdup Копіювання рядка у char *strdup(const char *s); Покажчик на область
створювану область пам’яті, що містить копію
пам’яті рядка
strrev Перевертання рядка char *strrev(char *s); Покажчик на рядок, що
змінився
strnset Заміна заданої char *strnset(char *s, int ch, Покажчик на рядок, що
кількості символів size_t n); змінився
на вказаний символ
strtok Визначення лексем, char *strtok(char *source, Покажчик на знайдену
відділених const char *separator); лексему. У процесі
роздільниками повторного виклику функції
для пошуку нових лексем
перший параметр функції
має бути NULL.
atoi Перетворення рядка #include <stdlib.h> int Число, що утворилося, або
у ціле число atoi(const char *s); 0, якщо перетворення
неможливе
atof Перетворення рядка #include <math.h> double Число, що утворилося, або
у дійсне число atof(const char *s); 0, якщо перетворення
неможливе
itoa Перетворення #include <stdlib.h> char Покажчик на рядок
цілого числа у *itoa(int value, char *string,
рядок int radix);
9.2. Приклад алгоритму та програми
//отримати рядок без зайвих пробілів на початку, в кінці та в середині
// рядку
#include<stdio.h>
#include<string.h>
#include<conio.h>
char str [80]; //початковий рядок
char *ptr; //покажчик на рядок
int i, j, k; //параметри циклу, кількість слів
//================вилучення початкових пропусків===================//
void delspacebeg(char s[80])//параметр s – рядок, що обробляється
{
k=0; //лічильник кількості пропусків
while(s[0]==' ') //доки першим символом є пропуск,
{
k++; //зсунути рядок вліво на кількість пропусків
for(i=0;i<strlen(s)-k;i++)

60
s[i]=s[i+1]; //зсунути символи рядка на позиції пропусків
}
printf ("Number of spacesymbol of beginning %d \n\n", k);
s[strlen(s)-k]='\0'; //довжину рядка зменшити на кількість вилучених
// пропусків
puts (s);
}
//==================вилучення кінцевих пропусків=================///
void delspaceend(char s[80])
{ ptr=strrchr(s,' '); //позиція останнього входження пропуску
if (ptr != 0)
while(s[ptr-s]==' ' && s[ptr-s+1]=='\0') //доки у кінці рядка пропуск
{ s[ptr-s]='\0'; //заміна пропуску на символ кінця рядка
ptr=strrchr(s,' '); //визначити покажчик на символ пропуску
}
puts(s);
printf("Length of string after delete last spaces %d \n\
n",strlen(s));
}
//=================вилучення проміжних пропусків===============//
void delbeetw(char s[80])
{ k=0; //кількість пропусків
for(i=0; i<strlen(s)-1; i++) {
while(s[i]==' ' && s[i+1]==' ') //доки є два підряд пропуски
{ k++; //лічильник пропусків, що йдуть підряд
for(j=i; j<strlen(s)-k; j++) //зсунути рядок вліво
s[j]=s[j+1];
s[strlen(s)-k]='\0'; //вилучити пропуски, що у кінці рядка
k=0; //обнулити лічильник пропусків для нового зсунення рядка
}
}
puts(s); //контрольне виведення
printf("Length of string after delete inside spaces %d \n\
n",strlen(s));
}
//============== підрахунок кількості слів у рядку s =======//
void word(char s[80])
{
s[strlen(s)]=' '; //додавання символа пробіл до кінця рядка
s[strlen(s)+1]='\0'; //вставка пропуску після останнього символа
for(i=0,k=0; i<strlen(s); i++)
if(s[i]==' '&&s[i+1]!=' ') //якщо не існує два підряд пропуски, то
k++; //починається k-е слово
printf("Number of words %d \n", k);
}
//================ головна програма ==============================//
void main()
{
puts("Input string:");
gets(str);
puts(str); //введення та виведення рядка
puts("");
printf("\nLength of string %d \n",strlen (str));
delspacebeg(str); //видалення пробілів на початку рядка
printf("length of string after deleted beginning spaces %d \n\
n",strlen(str));
delspaceend(str); //видалення пробілів у кінці рядка
delbeetw(str); //видалення пробілів у середині рядка
word(str); //визначення кількості слів
puts(str);
while(!kbhit()); //затримка зображення до натиснення будь-якої клавіші
}

61
Рис. 9.1. Результати роботи програми
9.3. Варіанти завдань
1. У рядку символів визначити кількість слів і знайти найдовше слово. Вилучити
з рядка однолітерні слова та зайві пропуски, коми, крапки. Слова відділяються один від
одного довільною кількістю пропусків, ком і крапок.
2. У рядку символів визначити кількість слів, що повторюються, та вилучити
дублікати. Слова відокремлюються пробілами.
3. З рядку вилучити всі слова на непарних порядкових позиціях, а слова на
парних позиціях надрукувати перевернутими.
4. Ввести два рядки, вилучити з першого рядка всі слова, які зустрічаються у
другому рядку.
5. Увести масив рядків, що є реченнями. Речення може займати більше, ніж один
рядок. Визначити найдовше речення і переписати його, помінявши місцями парні та
непарні слова.
6. Увести масив рядків. Розширити кожний рядок до довжини 60 символів,
додавши рівномірно пропуски між словами. Якщо початковий рядок містить більше 60
символів, то перенести зайві слова на новий рядок.
7. У рядку символів визначити слова-паліндроми, які однаково читаються справа
наліво і навпаки. Знайти найбільшу довжину цих слів. Якщо таких слів немає, то з
кожного слова на непарній позиції вилучити голосні та надрукуйте їх.
8. У рядку символів визначити слова, що починаються і закінчуються на літери,
значення яких уводять з клавіатури. Надрукувати їх у перевернутому вигляді (справа
наліво). Визначити частоту кожної голосної літери
9. Заданий рядок s1. Після видалення однієї літери з s1 утворюється рядок s2.
Після видалення з s1 іншої літери утворюється рядок s3. Потрібно за рядками s2 і s3
відновити рядок s1.
10. У рядку символів визначити слова, які можна одержати перевертанням слова,
що вводиться з клавіатури на запит користувача. Кожне друге слово розбити на склади.
11. У рядку визначити кількість однакових символів, що йдуть поспіль.
Надрукувати групи символів, що повторюються та вилучити повторення символів,
залишивши по одному. Розбити на склади найдовше слово.
12. У рядку слів визначити кількість слів і надрукувати ті, довжина яких більша за
вказану користувачем. Якщо слово починається із заданого користувачем символа, то
замінити слово на перше у рядку.

62
13. Увести парну кількість рядків. Вилучити з кожного парного рядка всі слова, які
зустрічаються у попередньому рядку. У кожному непарному рядку знайти слова, довжина
яких не перевищує N символів (значення N уводять з клавіатури) і вивести їх у
алфавітному порядку.
14. Увести рядок символів та отримати новий рядок, слова якого відсортовані за
алфавітом. Отримати інший рядок, у якому слова відсортовані за довжиною слів.
15. Увести рядок символів та підрахувати кількість повторень слів однакової
довжини. Вилучити всі слова заданої користувачем довжини. У рядку, що залишився,
кожне слово записати з великої літери.
16. Увести два рядки символів та замінити кожне слово на парній позиції першого
рядка на слово, що стоїть на непарній позиції у другому рядку. Кількість слів у рядках
може бути різною.
17. Розбити на склади згідно з правилами перенесення слів кожне слово на парній
позиції у рядку. Слова на непарних позиціях інвертувати (записати у зворотньому
порядку).
18. Задано рядок слів, між якими не менше одного пробілу. Вивести на екран
слова, в яких літери розташовані в алфавітному порядку. Якщо таких слів немає, то
замінити усі входження заданого користувачем символа на заданий підрядок.
19. Увести масив рядків. Рядки містять пробіли на початку та в кінці рядка.
Вирівняти рядки по лівому або по правому полю відповідно до вимог користувача,
вилучивши зайві пробіли.
20. Увести число та надрукувати його словесний еквівалент. Наприклад, введено
число 25, надруковано "twenty five".
21. Увести декілька рядків. Об'єднати перші два, встановивши довжину
об'єднаного рядка не більше за задану користувачем кількість символів. Символи, що
залишилися, приєднати до третього рядка. Повторити операцію для наступної групи
рядків.
22. Увести рядок символів, серед яких є цифрові, пробіли та алфавітні. Визначити
слова, які є паліндромами (симетричними), ідентифікаторами зміних, натуральними
числами.
23. Увести рядок, що містить арифметичний вираз (дужки, символи арифметичних
операцій, операнди). Визначити коректність виразу (парність дужок, коректність операцій
та операндів).
24. Увести два рядки символів. Визначити кількість замін, видалень, вставки
символів, які необхідно здійснити для того, щоб один із уведених рядків перетворити в
інший.
9.4 Контрольні запитання
1. Чим відрізняється поточна довжина рядка від його загальної довжини?
2. Як позначається кінець рядка?
3. Як ініціалізувати рядок під час його оголошення?
4. Як здійснити доступ до елемента рядка?
5. Як увести та вивести рядок?
6. Які бібліотечні функції визначені для змінних рядкового типу?
7. Чи можна виконати операції присвоєння рядків?
8. Як реалізуються операції порівняння рядків?
9. У чому особливість застосування функції розкладання рядка на лексеми?

63
Структури та масиви структур
Лабораторна робота 10
10.1 Теоретичні відомості
Структура - це тип даних користувача, який об'єднує дані різних типів.
Елементами структури можуть бути дані будь-якого типу. Елементи структури
називаються полями.
Оголошення структури задається у такому вигляді:
struct ім'я_типу_структури
{
тип ім'я_змінної;
тип ім'я_змінної;
................ ;
};
Оголошення структури обов'язково закінчується фігурною дужкою }, після якої
ставиться крапка з комою.
Оголошення структурного типу не резервує жодного простору в пам'яті, тільки
створює новий тип даних, який використовується у процесі оголошенні змінних. Пам'ять
для структури резервуватиметься під час оголошення змінної. Для визначення обсягу
пам'яті, який резервується для змінної структурного типу, використовується операція
sizeof(ім'я_типу_структури).
Структурна змінна оголошується як будь-яка змінна через ім'я або покажчик на
тип:
ім'я_типу_структури ім'я_змінної;
ім'я_типу_структури *ім'я_покажчика;

Доступ до елемента структури здійснюється через складене ім'я, яке утворюється


за допомогою операції точки через ім'я об'єкта чи посилан-ня:

ім'я_змінної_типу_структури.ім'я_поля_структури

Якщо задано покажчик на структурний тип, то для доступу до елемента структури


використовується складене ім'я, яке утворюється за допомогою операції стрілка:

ім'я_покажчика_на_тип_структури -> ім'я_поля_структури

У будь-якій функції можна оголошувати структурну змінну, але оголошення типу


структури треба подати як глобальне на початку програми.

Приклад:

#include <iostream>
struct anketa //структурний тип
{
char fio[20]; //поля структури
int year_birth;
float salary;
};
void main(){
anketa student, *pointer_student;
pointer_student = &student;
cin >> student.fio;
cin >> pointer_student-> salary ;
cout << student.fio;
cout << pointer_student->salary ;
}

64
Структурній змінній можна присвоїти значення іншої структурної змінної, можна
передавати як параметри у функцію і повертати в основну програму як результат роботи
функції над полями структури. Попередньо оголошений покажчик на структурну змінну
передається у функцію під час її виклику, щоб не створювати копії основного об'єкта.
Якщо у функцію передається покажчик на структурну змінну, то у процесі виклику
функції параметр замінюється на аргумент, значенням якого є адреса структурної змінної:
&ім'я_структурної_змінної
Якщо параметром є структура, то під час виклику функції аргументом є ім'я
структурної змінної.
Структурні змінні можна об'єднувати у масиви, кожний елемент якого - це
структурна змінна.Оголошення масиву структур:
ім'я_типу_структури ім'я_масиву_структур[кількість елементів];

Доступ до поля масиву структур здійснюється за допомогою індекса елемента:


ім'я_масиву_структур[індекс].ім'я_поля

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


значенням нульового елемента масиву:

ім'я_типу_структури *ім'я_покажчика; //оголошення покажчика


ім'я_покажчика = &ім'я_масиву_структур[0];

10.2. Приклад алгоритму та програми


Скласти програму, що створює масив структур. Кожна структура складається з
таких елементів: прізвище викладача, дисципліна, прізвище студента. Для викладача
задається посада, зарплата, для студента - середній бал, стипендія. Реалізувати запити:
– визначити викладачів і дисципліни з найвищим середнім балом;
– перерахувати стипендію таким чином: вилучити стипендію у студентів, середній
бал яких нижче за трійку, і розподілити їх стипендію серед інших студентів;
– визначити стипендіальний фонд (сумарний розмір стипендії) і порівняти його з
фондом зарплати викладачів.
Алгоритм задачі
1. Поки не вибрано команду меню Exit, відобразити пункти меню на екрані.
2. Вибрати пункт меню.
3. Якщо вибрано пункт меню "Введення початкових даних у масив структур", то
повторювати такі дії:
3.1. Задати індекс першого запису
3.2. Увести назву дисципліни, прізвище викладача, його посаду, зарплату;
3.3. Для кожного викладача повторювати введення з клавіатури прізвища,
середнього бала та стипендії студентів;
3.4. Якщо натиснуто клавішу <n> для припинення введення, то кінець введення
даних.
4. Якщо вибрано пункт меню "Виведення відомостей про викладачів", то
повторювати такі дії:
4.1. Вибрати перший запис;
4.2. Вивести дані про викладача на екран;
4.3. Якщо не кінець масиву, то перейти до наступного запису
5. Якщо вибрано пункт меню "Виведення відомостей про студентів", то
повторювати такі дії:
5.1. Вибрати перший запис;
5.2. Вивести дані про студента на екран;
5.3. Якщо не кінець масиву, то перейти до наступного запису

65
6. Якщо вибрано пункт меню "Пошук дисципліни з найвищим середнім балом", то
повторювати такі дії:
6.1. Переглядати масив з першого запису;
6.2. Накопичувати суму балів студентів з окремої дисципліни;
6.3. Знайти середній бал успішності з конкретної дисципліні;
6.4. Якщо кінець масиву, то вивести середні бали з усіх дисциплін;
6.5. Знайти максимальний середній бал серед дисциплін;
6.6. Вивести остаточні результати.
7. Якщо вибрано пункт меню "Перерозподіл стипендій", то повторювати дії:
7.1. Цикл перебирання масиву студентів:
7.1.1. Накопичення суми балів з різних дисциплін для конкретного студента;
7.1.2. Розрахувати кількість дисциплін, які вивчає конкретний студент;
7.1.3. Розрахувати середній бал з усіх предметів для конкретного студента;
7.1.4. Сортування прізвищ студентів за алфавітом;
7.1.5. Вивести дані про загальний середній бал і введену стипендію;
7.1.6. Якщо оброблено дані про останнього студента, то кінець циклу,
інакше перейти до наступного студента.
7.2. Обробити дані про студентів з середнім балом меншим за трійку:
7.2.1. Розрахувати суму стипендій студентів, що мають середній бал,
менший трьох;
7.2.2. Розрахувати кількість студентів, яким треба перерахувати стипендію.
7.2.3. Цикл перебирання масиву студентів:
7.2.3.1. Якщо середній бал від трійки до п'ятірки, то до початкової стипендії
додається стипендія, яка знімається з студентів із середнім балом, меншим за трійку;
7.2.3.2. Вивести результати перерозподілу стипендій;
7.2.3.3. Якщо дані по всіх студентах оброблено, то кінець циклу.
8. Якщо вибрано пункт меню "Вихід", то завершити програму.
9. Якщо вибрано неіснуючий пункт меню, то вивести відповідне повідомлення.

Приклад коду
#include<iostream>
#include<conio.h>
#include<string.h>
#include<iomanip> //бібліотека маніпуляторів уведення-виведення
using namespace std;
/////////////// оголошення структур ///////////////////
struct teacher //структура даних про викладача
{
char fio[10]; //прізвище
char posada[20]; //посада
float salary; //зарплатня
};
struct stud //структура даних про студента
{
char fio[10]; //прізвище
float bal; //середній бал
float stip; //стипендія
};
struct subject //структура даних про дисципліни
{
char name[10]; //назва дисципліни
teacher prepod; //викладач, який читає дисципліну
int stnum; //кількість студентів, які вивчають цю дисципліну
stud student[10] ; //масив студентів, які вивчають дисципліну
};
subject predmet[10]; //масив дисциплін

66
int n; //кількість записів
///////////////////// Введення даних ////////////////////
void input()
{
char answer_prep, //параметр закінчення введення даних про викладача
answer_stud; //параметр закінчення введення даних про студента
int i=0; //початкове значення лічильника кількості дисциплін
do
{ //уведення даних про викладача
cout<<"subject name"<<endl; //уведення назви дисципліни
cin>>predmet[i].name; //уведення назви дисципліни
cout<<"teacher\'s surname"<<endl;
cin>>predmet[i].prepod.fio;
cout<<"teacher\'s position"<<endl;
cin>>predmet[i].prepod.posada;
cout<<"teacher\'s salary"<<endl;
cin>>predmet[i].prepod.salary;
int j=0; //початкове значення лічильника кількості студентів
do
{
//уведення даних про студента, який навчається у конкретного викладача
cout<<"student\'s surname"<<endl;
сin>>predmet[i].student[j].fio;
cout<<"student\'s ball on subject"<<endl;
cin>>predmet[i].student[j].bal;
cout<<"student\'s stipend"<<endl;
cin>>predmet[i].student[j].stip;
j++; //перехід до індексу наступного студента
cout<<"any students else? y/n"<<endl;
answer_stud=getch();
} while(answer_stud!='n'); //кінець введення даних про студента
predmet[i].stnum=j; //кількість студентів, які вивчають і-у
// дисципліну
cout<<"contunue input? y/n"<<endl;
answer_prep=getch();
i++; //перехід до нової дисципліни
} while (answer_prep!='n'); //кінець введення даних про викладача
n=i; //кількість викладачів
getch(); //чекати натиснення клавіші
} //кінець функції input()
/////////////////// виведення даних ///////////////////////
void output()
{
for(int i=0;i<n;i++)
{
cout<<"subject------teacher----position-----salary"<<endl;
cout.setf(ios::left); //вирівнювання даних на екрані зліва
cout<<setw(12)<<predmet[i].name<<setw(12)<<predmet[i].prepod.fio<<
setw(13)<<predmet[i].prepod.posada<<predmet[i].prepod.salary<<endl;
cout<<"____Students"<<endl;
cout<<" fio--------ball-----stipend"<<endl;
for(int j=0;j<predmet[i].stnum;j++) //виведення даних про студентів
{
cout.setf(ios::left);
cout<<setw(12)<<predmet[i].student[j].fio<<setw(10)<<
predmet[i].student[j].bal<<predmet[i].student[j].stip<<endl;
}
}
getch(); //чекати натиснення клавіші
} //кінець функції read_from_file()
//////////////// виведення даних про викладачів /////////////
void list_prepod()
{
cout<<"---subject----teacher-----position-----salary \n";

67
for(int i=0;i<n;i++)
{
cout.setf(ios::left); //виведення даних про викладачів
cout<< setw(10)<<predmet[i].name<<setw(12)<<predmet[i].prepod.fio<<

setw(14)<<predmet[i].prepod.posada<<predmet[i].prepod.salary<<endl;
}
getch(); //чекати натиснення клавіші
}
/////// пошук дисципліни з найвищім середнім балом ////////////
void maxbal()
{
float sr[10];
int i; //середній бал
for(i=0;i<n;i++)
{
sr[i]=0; //сума балів успішності по і-й дисципліні
for(int j=0;j<predmet[i].stnum;j++) //перегляд даних про студентів
//сума балів студентів з дисципліни
sr[i]+=predmet[i].student[j].bal;
sr[i]=float(sr[i])/predmet[i].stnum; //середній бал з конкретної
//дисципліні
}
cout<<" Subject\'s average ball"<<endl;
for (int i=0;i<n;i++) //цикл виведення даних про всіх викладачів
{
cout.setf(ios::left);
cout<<setw(10)<<predmet[i].name<<setw(5)<<sr[i]<<endl;
}
cout<<" subject with the highest ball: "<<endl;
float max=sr[0]; //максимальний бал
int nomer_predmet=0; //індекс дисципліни у масиві дисциплін
//пошук найбільшого середнього бала з усіх дисциплін
for(int i=1;i<kol_prep; i++)
if (max<sr[i])
{
max=sr[i];
nomer_predmet=i;
}
cout<<" max ball="<<max<<" in subject "<<
predmet[nomer_predmet].name<<
" teacher "<<predmet[nomer_predmet].prepod.fio<<endl;
getch(); //чекати натиснення клавіші
} //кінець функції maxbal()
////////////// перерозподіл стипендій /////////////////
void stipendia()
{
float sum=0; //сума стипендій студентів з середнім балом меншим трьох
int k=0; //кількість записів про студентів у вхідному масиві
int m=0; //лічильник кількості студентів
stud s,tmp[10],stud_tmp[10]; //проміжні масиви студентів
//копіювання даних про студентів у масив без дисциплін і прізвищ викладачів
for(int i=0;i<n;i++)
for(int j=0;j<predmet[i].stnum;j++) //обробка масиву студентів
{ //копіювання масиву студентів
tmp[k]=predmet[i].student[j];
k++;
}
//===розрахунок середнього бала студентів, що вивчають різні дисципліни =====
int kol[10]; //лічильник дисциплін, які вивчає один студент
for (int i=0;i<k;i++)
{ //перегляд усього масиву студентів
stud_tmp[m].bal=0; //сума балів одного студента з різних дисциплін
kol[m]=0; //кількість дисциплін для одного студента

68
int f=0; //прапорець обробки даних про студента
//перегляд даних про студентів від початку масиву до конкретного запису
for (int j=0;j<i;j++)
if ((strcmp(tmp[i].fio,tmp[j].fio)==0))
f=1; //відомості про студента вже зустрічалися в масиві
if (f==0) //відомості про студента ще не зустрічалися в масиві
{
for (int j=i;j<k;j++) //перегляд масиву студентів
if (strcmp(tmp[i].fio,tmp[j].fio)==0) //студент вивчає
// інший предмет
{
stud_tmp[m].bal+=tmp[j].bal; //накопичення балів
// одного студента
strcpy(stud_tmp[m].fio, tmp[j].fio); //запам’ятати
// прізвище студента
stud_tmp[m].stip=tmp[j].stip; //запам’ятати
//розмір стипендії
kol[m]++; //вибір наступної дисципліни
}
stud_tmp[m].bal=float(stud_tmp[m].bal)/kol[m]; //розрахунок
// середнього бала
m++; //перехід до наступного студента
} // end of if (f==0)
} //end of for I
//================ сортування студентів за алфавітом =================
int all_stud=m; //загальна кількість студентів
for (int i=0;i<all_stud;i++)
for(int j=i+1;j<all_stud;j++)
if (strcmp(stud_tmp[i].fio,stud_tmp[j].fio)>0)
{
s=stud_tmp[i];
stud_tmp[i]=stud_tmp[j];
stud_tmp[j]=s;
}
//=== виведення даних про загальний середній бал і початкову стипендію ====
cout<<"Array of students after sort"<<endl;
cout<<"—student------average ball------stipend"<<endl;
for (int i=0;i<all_stud;i++)
{
cout.setf(ios::left);
cout<<setw(20)<<stud_tmp[i].fio<<setw(15)<<stud_tmp[i].bal<<
stud_tmp[i].stip<<endl;
}
getch();
// ================== перерозподіл стипендій =======================
int j=0; //кількість студентів
for (int i=0;i<all_stud;i++)
if ((stud_tmp[i].bal>=0)&&(stud_tmp[i].bal<3)) //умови зняття стипендій
{
sum+=stud_tmp[i].stip;
stud_tmp[i].stip=0; //обнуління даних про стипендії
j++;
}
//розподіл стипендії між студентами, які добре вчаться
for (int i=0;i<all_stud; i++)
if ((stud_tmp[i].bal>=3)&&(stud_tmp[i].bal<=5))
stud_tmp[i].stip=stud_tmp[i].stip+sum/(all_stud-j);

//=============== виведення нарахованої стипендії =================


//виведення заголовка таблиці
cout<<endl<<"Counted stipend"<<endl;
cout<<"—FIO------average ball------stipend"<<endl;
//виведення даних з масиву студентів
for(int i=0;i<all_stud;i++)

69
{
cout.setf(ios::left);
cout<<setw(15)<<stud_tmp[i].fio<<setw(15)<<stud_tmp[i].bal;
if ((stud_tmp[i].bal>=3)&&(stud_tmp[i].bal<=5))
cout<<stud_tmp[i].stip<<endl;
else
cout<<"has no stipend"<<endl; //стипендію не нараховано
}
getch(); //чекати натиснення клавіші
} //кінець функції stipendia()
///////////////// виведення даних про студентів //////////////////
void list_student()
{
cout<<"---teacher----student-----ball----stipend \n";
for(int i=0;i<n;i++)
{
cout<<" "<<predmet[i].prepod.fio<<endl; //прізвища викладача
//вибір студентів, які навчаються у конкретного викладача
for(int j=0;j<predmet[i].stnum;j++)
{
cout.setf(ios::left); //виведення даних про студентів
cout<<setw(12)<<predmet[i].student[j].fio<<setw(10)<<
predmet[i].student[j].bal<<predmet[i].student[j].stip<<endl;
}
}
} //кінець функції list_student()

//////////////////// головна програма //////////////////


void main()
{
while (1)
{
system("cls");
cout<<" MENU \n"<<endl;
cout<<"1. Database input by keyboard."<<endl;
cout<<"2. Output data."<<endl;
cout<<"3. View teacher\’s database."<<endl;;
cout<<"4. View student\’s database."<<endl;
cout<<"5. List of subjects with the highest average ball."<<endl;
cout<<"6. Stipend."<<endl;
cout<<"7. Stipend found."<<endl;
cout<<"8. Exit"<<endl;
cout<<endl;
int key; //номер пункту меню
cout<< "Choosen menu item:";
cin>>key; //вибір потрібного пункту меню
switch(key) //вибір функції реалізації меню
{
case 1: {input();break;} //введення даних
case 2: {output();break;} //виведення даних з масиву на екран
case 3: {list_prepod();break;} //виведення даних про викладачів
case 4: {list_student();break;} //виведення даних про студентів
case 5: {maxbal();break;} //пошук дисципліни з найвищім балом
case 6: {stipendia();break;} //перерозподіл стипендій
case 8: {exit (0); break;} //вихід з програми
default: {cout<<"Try another time...";getch();break;}
}
}
} //кінець функції main()

70
Рис. 10.1. Результати роботи програми. Виконання меню 2

Рис. 10.2. Результати роботи програми. Виконання меню 5

Рис. 10.3. Результати роботи програми. Виконання меню 6

71
10.3. Варіанти завдань
1. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити,
визначивши: 1) прізвища студентів, які мають дві та більше двійок за сесію на факультеті
ІОТ і вилучити їх; 2) факультет, який на першому курсі має найбільшу кількість
відмінників; 3) курс, на якому виключено найбільшу кількість студентів.
2. Створити масив структур. Кожна структура складається з таких елементів:
фірма, вакантна посада, кількість вакантних місць, вимоги до претендентів на кожну
посаду, заробітна платня. Реалізувати запити: 1) визначити фірми з найбільшою кількістю
вакансій на задану посаду; 2) вивести список вимог до кандидатів на задану посаду по
кожній фірмі; 3) створити новий масив із структурою: вакантна посада, заробітна платня.
Вакансії вибирати з початкового масиву, виключаючи повторення однакових вакантних
посад. На випадок різної платні на однакових посадах у різних фірмах включити у масив
середню заробітну платню.
3. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити: 1)
визначити факультет і курс з максимальною кількістю відмінників; 2) вивести список
відмінників; 3) знайти групу, де немає двієчників.
4. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити,
визначивши: 1) факультет і курс, на якому середній бал не менше 3.5; 2) прізвища
студентів, що не мають трійок і двійок; 3) факультет і групу, де найбільше відмінників.
5. Створити масив структур. Кожна структура складається з таких елементів:
місто, інститут, факультет, список спеціальностей, план прийому на перший курс.
Реалізувати запити, визначивши: 1) список спеціальностей, що містять у своїй назві слова
"комп'ютерний" або "автоматизований"; 2) факультети й інститути, де є задана
спеціальність; 3) факультет, інститут і місто, де на вказану користувачем спеціальність
виділено найбільше місць.
6. Створити масив структур, кожна з яких складається з наступних елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити:
1) визначити прізвища студентів, групу і факультет, де середній бал студентів 4.5;
2) вилучити прізвища студентів першого курсу, які мають три двійки; 3) відсортувати
назви факультетів за умови зростання успішності студентів.
7. Створити масив структур. Кожна структура складається з таких елементів:
марка автомобіля, тип (вантажний або легковий), номерний знак, строк служби. Для
легкових вказується колір, для вантажних - вантажність. Реалізувати запити: 1) визначити
номерні знаки автомобілів, вантажність котрих не менше за задану; 2) вивести марки
автомобілів заданого типу і вказаного кольору; 3) вилучити з масиву відомості про
автомобілі, строк служби яких перевищує п'ять років.
8. Створити масив структур. Кожна структура складається з таких елементів:
прізвище абонента, номер телефону, адреса, заборгованість по оплаті. Реалізувати запити:
1) визначити прізвища абонентів, що мають заборгованість по оплаті більше заданої
користувачем; 2) вилучити прізвища абонентів, адреса яких змінилася; 3) замінити номер
телефону заданого абонента.
9. Створити масив структур. Кожна структура складається з таких елементів:
фірма, найменування товару, що продається, вартість, термін поставки товару. Реалізувати
запити: 1) визначити фірми, що постачають заданий товар у дводенний строк;
2) визначити назву товару в заданій фірмі, вартість якого не перевищує заданого значення;
3) впорядкувати масив за умови зростання термінів постачання товару.
10. Створити масив структур. Кожна структура складається з таких елементів:
інститут, факультет, список спеціальностей, план прийому на перший курс, прохідний
бал. Реалізувати запити: 1) скласти список спеціальностей по факультетах із вказаним
72
прохідним балом; 2) впорядкувати масив за прохідним балом і планом прийому; 3)
визначити інститут із вказаним середнім прохідним балом.
11. Створити масив структур. Кожна структура складається з таких елементів:
номер авіаційного рейсу, тип літака, дата відльоту, кількість вільних місць, вартість
квитка. Реалізувати запити: 1) скласти список номерів авіаційних рейсів, на які є вільні
місця; 2) вивести типи літаків і відповідні номери авіаційних рейсів на задану дату;
3) упорядкувати масив за умови зростання вартості квитків по кожній даті.
12. Створити масив структур. Кожна структура складається з таких елементів:
напрям польоту, номер авіаційного рейсу, типи літаків, кількість посадкових місць,
вартість квитка, льотні дні на тиждень. Реалізувати запити: 1) визначити номери
авіаційних рейсів заданого напрямку з мінімальною вартістю квитків; 2) визначити типи
літаків і сумарну кількість посадкових місць у заданому напрямку по днях тижня;
3) вилучити з масиву відомості про рейси, якщо кількість польотів на тиждень менше
двох. .
13. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити,
визначивши: 1) групи на першому і другому курсах, в яких більше п'яти відмінників; 2)
факультети, де немає двієчників; 3) прізвища студентів, що не з'явилися хоча б на один
іспит (оцінка 0).
14. Створити масив структур. Кожна структура складається з таких елементів:
прізвище абонента, номер телефону, адреса, вид оплати (щохвилинна чи абонементна),
вартість оплати. Реалізувати такі операції: 1) доповнити масив прізвищами абонентів,
номери телефонів яких починаються на задані цифри (імітувати введення нової АТС);
2) видати список абонентів з щохвилинною оплатою, сума оплати у яких нижче заданого
рівня; 3) визначити номер телефону абонента за заданою адресою.
15. Створити масив структур. Кожна структура складається з таких елементів:
напої та шоколадні вироби; їх калорійність, вартість. Для напоїв вказати міцність, для
шоколадних виробів - вагу, начинку. Реалізувати запити: 1) визначити список шоколадних
виробів, що мають максимальну вагу і задану начинку; 2) вилучити з масиву інформацію
про алкогольні напої; 3) скласти меню з напоїв і шоколадних виробів, що відповідають
заданій калорійності та вартості.
16. Створити масив структур. Кожна структура складається з таких елементів:
продукт, ціна продукту, рівень корисності продукту (функцію корисності задати у
довільному вигляді), прибуток споживача. Реалізувати запити, визначивши: 1) продукти
заданого рівня корисності, які може придбати споживач при заданому прибутку;
2) сумарну вартість продуктів з максимальним рівнем корисності; 3) споживачів,
прибутків яких не вистачає для придбання продуктів за заданою ціною і рівнем
корисності.
17. Створити масив структур. Кожна структура складається з таких елементів:
місто, інститут, факультет, список спеціальностей, план прийому на перший курс,
прохідний бал. Реалізувати запити, визначивши: 1) список міст, де знаходяться
політехнічні інститути; 2) інститути і факультети, де приймають студентів на перший курс
за заданою користувачем спеціальністю; 3) факультет, інститут і місто, де на вказану
користувачем спеціальність існує найвищий прохідний бал.
18. Створити масив структур. Кожна структура складається з таких елементів:
факультет, прізвища студентів, прізвища викладачів. Для студентів вказують стипендію і
середній бал. Для викладачів - посаду і заробітну плату. Реалізувати запити, визначивши:
1) список студентів по факультетах з найнижчим середнім балом і стипендією; 2) кількість
викладачів-доцентів на заданому факультеті; 3) сумарний фонд стипендії і зарплати на
заданому факультеті.
19. Створити масив структур. Кожна структура складається з таких елементів:
назва фірми, продукт, що продається - комп'ютери і програмне забезпечення, регіон збуту,

73
вартість продажу, термін постачання. Реалізувати запити, визначивши: 1) список
комп'ютерів, що продаються у заданому регіоні конкретною фірмою; 2) вартість
проданого програмного забезпечення у задані терміни; 3) найрентабельніші фірми (з
найбільшою вартістю продажів).
20. Створити масив структур. Кожна структура складається з таких елементів:
прізвище студента, курс, середній бал. Для студентів контрактної форми навчання
вказується вартість контракту, а для студентів, що навчаються за бюджетною формою -
розмір стипендії. Реалізувати такі операції: 1) визначити прізвища студентів із середнім
балом вище четвірки, надрукувати окремо студентів контрактної та бюджетної форм
навчання; 2) вилучити дані про студентів бюджетної форми з масиву, якщо їх середній бал
нижче трійки; 3) вивести список студентів контрактної форми і суму їх контрактів.
21. Створити масив структур. Кожна структура складається з таких елементів:
книги, журнали. Для книжок задають назву, прізвище автора, рік видання. Для журналів -
назву, номер, рік видання, назву статті, автора. Реалізувати запити: 1) вивести авторів, які
друкувалися у вказаному році та їх праці; 2) визначити журнал, рік видання вказаної
статті; 3) вивести кількість статей заданого автора і журнали, у яких він друкувався.
22. Створити масив структур. Кожна структура складається з таких елементів:
прізвище викладача, дисципліна, прізвища студентів, що вивчають конкретну дисципліну.
Для викладача задають посаду, заробітну плату, для студента - середній бал і стипендію.
Реалізувати такі запити: 1) визначити викладачів і дисципліни з середніми балами менше
заданого; 2) вилучити студентів, середній бал яких нижче за трійку; 3) визначити
стипендіальний фонд студентів (кількість студентів, що отримають стипендію, помножену
на розмір стипендії), які вивчають задану дисципліну.
23. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки, стипендія. Реалізувати
запити, визначивши: 1) прізвища студентів, що мають стипендію, їх середній бал;
2) факультет, на якому на першому курсі найбільша кількість груп студентів, що не мають
двійок; 3) курс з найбільшою кількістю відмінників.
24. Створити масив структур. Кожна структура складається з таких елементів:
факультет, курс, група, прізвища студентів, екзаменаційні оцінки. Реалізувати запити,
визначивши: 1) кількість факультетів, де середній бал студентів від трьох до чотирьох; 2)
видалити прізвища студентів-двієчників другого курсу факультетів, середній бал яких
вище 3.5; 3) упорядкувати масив структур за умови зростання середнього бала на
факультеті ФІОТ.
25. Створити масив структур. Кожна структура складається з таких елементів:
місто, фірма, продукт, кількість продукту, ціна одиниці продукту, вартість продуктів.
Реалізувати запити: 1) визначити місцезнаходження фірми, що виробляє заданий продукт;
2) визначити сумарну вартість продуктів, що виробляються у даному місті;
3) упорядкувати список продуктів за ціною для даного міста.
10.4 Контрольні запитання
1. Дати поняття структурного типу даних та оголошення структурної змінної,
масиву структур.
2. Як здійснюється доступ до елементів структури?
3. Як передати структуру або масив структур до функції як аргумент?
4. Як повернути з функції масив структур?
5. Які операції можна виконувати із структурами?
6. Як визначається обсяг пам'яті, що потребує структура, і коли вона
резервується?

74

You might also like