Professional Documents
Culture Documents
Method Lab Work ANSI C 2010 Lab1-10 v2
Method Lab Work ANSI C 2010 Lab1-10 v2
Київ 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 Характеристика типів змінних
Тип Назва типу Обсяг Діапазон значень
оперативної
пам’яті
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 при невдалому
для перетворення типів введенні
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 Математичні функції
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
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
14
1.4. Варіанти завдань
Усі користувачі розробляють програму за власним сценарієм відповідно до
наведених прикладів. Варіанти завдань для даної лабораторної роботи не приводяться. В
процесі виконання лабораторної роботи користувач повинен:
1. Увести з клавіатури і вивести на екран значення змінних різних типів згідно з
форматами даних (форматне введення-виведення) і без використання форматів.
Використати всі функції, що приведені у таблиці 1.2.
2. Визначити розбіжності у використанні функцій введення - виведення.
3. За даними, що введені з клавіатури в оперативну пам’ять, визначити значення
виразу, використовуючи математичні функції, і вивести результат на екран. Вираз вибрати
згідно з варіантом по таблиці 1.7. Значення змінних A,B,C,D задати самостійно.
Таблиця 1.7. Арифметичні вирази
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):
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;
} //кінець програми
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. (рівнобедрений, рівнобокій, прямокутний,
різнобокій, не існує).
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.
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-го
void ім'я_функції(void);
ім'я_функції(аргументи);
Якщо функція повертає будь-яке значення, то під час її виклику це значення треба
присвоїти змінній відповідного типу. Формат оператора виклику такий:
ім'я_змінної = ім'я_функції(аргументи);
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> //підключення бібліотек математичних функцій
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. Визначити похибку.
32
6. Обчислити значення функції у, розвинувши функцію arctg(x) у ряд Тейлора.
Аргумент х змінюється від 0 до 3 з кроком 0.5. Визначити похибку.
.
13.Обчислити значення функції у, розвинувши функцію у ряд Тейлора. Аргумент х
змінюється від -2 до 2 з кроком 0.5. Визначити похибку.
33
14. Обчислити значення функції у, розвинувши функцію tg(x) у ряд Тейлора.
Аргумент х змінюється від -3 до 3 з кроком 0.5. Визначити похибку.
34
24. Обчислити значення функції у, розвинувши функцію ln(x) у ряд Тейлора.
Аргумент х змінюється від -2 до 4 з кроком 0.5. Визначити похибку.
35
Рекурсивні функції
Лабораторна робота 5
Мета роботи.
вивчити особливості рекурсивних процесів
опанувати технологію рекурсивних обчислень
навчитися розробляти алгоритми та програми із застосуванням
рекурсивних функцій
5.1 Теоретичні відомості
Означення називається рекурсивним, якщо воно задає елементи множини за
допомогою інших елементів цієї самої множини. Об' єкти, що задані рекурсивним
означенням, також називаються рекурсивними. Під терміном "рекурсивно задана функція"
розуміється така функція, значення якої для данноrо apгумента обчислюється за
допомогою значень для попередніх apгументов. При кожній конкретній реалізації процес
обчислення такої функції задається рекурентною послідовністю. У практиці обчислень це
пов'язано з тим, що, маючи справу з реальною функцією, ми не обчислюємо її в реальному
завданні на усій числовій осі, а обчислюємо для деякої кінцевої послідовності значень
apгументов.
Рекурсія — це такий спосіб організації обчислювального процесу, за якого функція
звертається сама до себе. Такі звернення називаються рекурсивними викликами, а функція,
що містить рекурсивні виклики, — рекурсивною.
Перед тим, як записати рекурсивну функцію будь-якою мовою програмування,
необхідно записати рекурентне співвідношення, що визначає метод обчислення функцій.
Рекурентне співвідношення повинне містити як мінімум дві умови:
умову продовження рекурсії (крок рекурсії);
умову закінчення рекурсії.
Розглянемо функцію , де аргумент є цілим додатним числом, таким, що
або . Потрібно обчислити значення членів послідовності Рекурсивне
завдання послідовності як послідовності значень функції включає такі два етапи.
1. Функція задається безпосередньо у вигляді числових значень для деякої
конечної множини початкових значень аргументу .
2. Задається метод або формула, які дозволяють, знаючи усі значення функції
при , обчислити її значення при , тобто знайти .
В результаті отримуємо peкуррентні співвідношення, що описують рекурсивно
задану функцію , рівносильну послідовності .
Отриманий запис цих двох етапів
36
Програмний код, що реалізує рекурсивні обчислення, такий:
int Fib(int n)
{
if (n == 0) return 0;
else if (n == 1) return 1;
else return Fib(n–1)+Fib(n–2);
}
Підказка. Умова продовження рекурсії: сума цифр числа дорівнює останній цифрі
плюс сума цифр числа без останньої цифри (числа, що ділиться без остачі на 10). Умова
закінчення рекурсії: якщо число дорівнює 0, то сума його цифр дорівнює 0.
2. Знайти кількість одиниць в двійковому представленні числа n та значення
глибини рекурсії, використовуючи рекурентне означення функції f(n) (& - операція
побітового логічного множення):
37
3. Знайти значення біноміального коефіцієнта при заданих n, k за формулою:
= ,
38
Визначити глибину рекурсії та обчислити функції за заданими значеннями
:
39
15. Для числа, що введено з клавіатури, визначити рекурсивні функції для
обчислення суми та кількості його цифр, максимальної та мінімальної цифри. Визначити
рекурентні співвідношення та глибину рекурсії.
16. Задати з клавіатури перший член і різницю арифметичної прогресії. Визначити
рекурсивні функції для знаходження -го члена арифметичної прогресії та суми її
членів. Визначити рекурентні співвідношення та глибину рекурсії.
17. Задати з клавіатури перший член і знаменник геометричної прогресії.
Визначити рекурсивні функції для знаходження -го члена геометричної прогресії та суми
її членів. Визначити рекурентні співвідношення та глибину рекурсії.
18. Визначити добуток двох комплексних чисел . Вхідні
значення – числа . Результат – числа . Використати рекурсивний алгоритм
Карацуби.
Підказка. З алгоритмом Карацуби початкові операнди множення подаються
як вирази , де для 32-бітних процесорів,
визначається як половина розміру (в 32-бітових словах) мінімального по довжині
множника. Таким чином, початкові множники розбиваються на молодшу і старшу частині.
Після розбиття операндів виконується розрахунок проміжних значень:
має межу при і знайти значення цієї межі. Визначити глибину рекурсії під час
розрахунку.
21. Задані натуральні числа а, c, m. Визначити рекурсивну функцію та глибину
рекурсії для обчислення за формулою:
, де
40
- залишок від ділення на 10.
22. Двійкові числа довжини складаються з нулів і одиниць. Нехай –
функція, значенням якої є кількість двійкових чисел довжини , що не містять двох або
більше одиниць поспіль. Визначити рекурентне співвідношення, яке задає функцію ,
надрукувати такі числа, підрахувати їх кількість.
23. По заданим b, p, m обчислити значення виразу . Обчислення
виконати, використовуючи алгоритм, що базується на двійковому розкладанні показника
степені p:
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)|> ε. Для визначення
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); //точність розрахунків досягнута
}
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. Використовуючи покажчики на функції для їх викликів, обчислити
ланцюговий дріб
ланцюговий дріб
ланцюговий дріб
46
Використати функції, що повертають покажчики на цілий тип та використовують
покажчики як параметри.
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
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");
}
50
7.3. Варіанти завдань
1. Створити одновимірний массив, кількість елементів якого задана
користувачем. У масиві поміняти місцями максимальний і мінімальний елементи.
Надрукувати вхідний та вихідний масиви.
2. Створити одновимірний массив, кількість елементів якого задана
користувачем. Упорядкувати масив у порядку зростання, підрахувати кількість
переставлень елементів та їх порівнянь. Надрукувати вхідний та вихідний масив.
3. Заданий одновимірний масив А, кількість елементів якого задана
користувачем. Побудувати масив В, кожний елемент якого обчислюється за формулою
, де - максимальний елемент масиву А. Надрукувати вхідний та вихідний
масиви.
4. Задані одновимірні масиви А, В з 10 чисел. Побудувати масив С, кожний
елемент якого обчислюється за формулою:
52
Багатовимірні масиви
Лабораторна робота 8
8.1 Теоретичні відомості
8.1.1. Оголошення багатовимірних масивів. Доступ до елементів
Синтаксис оголошення змінної матричного типу в мовах С/C++:
<тип елементів> <ім’я матриці> [<кількість рядків>][<кількість
стовпців>];
У цьому оголошенні <тип елементів> — будь- який тип даних, окрім файлового
типу; <ім’я матриці> — деякий ідентифікатор; <кількість рядків> і <кількість стовпців> —
константи, що визначає розмірність матриці. Межі діапазону допустимих значень індексів
рядків і стовпців визначаються значеннями від 0 до <кількість рядків>–1 та від 0 до
<кількість стовпців>–1. Масиви, що мають більш ніж два виміри, оголошуються в
аналогічний спосіб.
Доступ до елементів матриці здійснюється операцією індексування [] за двома
індексами, які визначають номер рядка та номер стовпця елемента. Синтаксис операції
індексування є таким:
<ім’я масиву>[<номер рядка>][<номер стовпця>]
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;
}
k 1
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. Задати матрицю розмірності mn (m, n 3). Починаючи з лівого нижнього кута
матриці та рухаючись лише праворуч і догори, досягти її правого верхнього кута і вибрати
при цьому такі значення елементів, що їх сума буде максимальною. Вивести перелік
вибраних елементів.
21. Знайти добуток довільної кількості матриць довільної розмірності. Кількість
матриць, які треба перемножити, їх розмірність і значення елементів задаються
користувачем.
22. Для заданої матриці та вектора довільної вимірності здійснити множення
матриці та вектор та вектора на матрицю.
23. Для заданої матриці довільної вимірності визначити вектор, -ий елемент
котрого дорівнюватиме 1, якщо елементи -го рядка матриці впорядковані за спаданням,
та 0, якщо -ий рядок матриці є симетричним.
24. В заданій матриці довільної вимірності обчислити суму елементів парних
рядків, найбільші значення у непарних рядках, середнє арифметичне серед від’ємних
елементів матриці та індекси нульових елементів.
57
Обробка рядків
Лабораторна робота 9
9.1 Теоретичні відомості
9.1.1. Визначення рядка
Рядок - це масив символів, який закінчується символом кінця рядка ' \0'. Значенням
символа є ціле число, яке є кодом таблиці символів ASCII. Символ відображається у
одинарних лапках, наприклад: 'z'. Кожний символ в оперативній пам'яті займає один
байт. Рядок характеризується дов-жиною, яка дорівнює кількості символів, та обсягом
пам'яті. Обсяг пам'яті, який займає рядок, на одиницю більший за довжину рядка за
рахунок символа кінця рядка '\0'.
Кожний символ рядка має свій індекс. Доступ до символа рядка здійснюється за
допомогою операції [ ]. Рядок і всі його символи мають одне ім'я. При оголошенні рядка
задаються ім'я та кількість елементів рядка. Довжина рядка визначається читанням
символа кінця рядка '\0' під час введення рядка. Для позначення нового рядка
використовується символ '\n'.
Рядок доступний через покажчик (адресу) на перший символ у рядку. Таким чином,
ім'я рядка - це покажчик на перший символ.
Формати оголошення рядка:
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
Структурній змінній можна присвоїти значення іншої структурної змінної, можна
передавати як параметри у функцію і повертати в основну програму як результат роботи
функції над полями структури. Попередньо оголошений покажчик на структурну змінну
передається у функцію під час її виклику, щоб не створювати копії основного об'єкта.
Якщо у функцію передається покажчик на структурну змінну, то у процесі виклику
функції параметр замінюється на аргумент, значенням якого є адреса структурної змінної:
&ім'я_структурної_змінної
Якщо параметром є структура, то під час виклику функції аргументом є ім'я
структурної змінної.
Структурні змінні можна об'єднувати у масиви, кожний елемент якого - це
структурна змінна.Оголошення масиву структур:
ім'я_типу_структури ім'я_масиву_структур[кількість елементів];
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);
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()
70
Рис. 10.1. Результати роботи програми. Виконання меню 2
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