Professional Documents
Culture Documents
практика-2023 ч1
практика-2023 ч1
1)
до літньої обчислювальної практики
І курс
спеціальність 122 – «Комп’ютерні науки»
ОП «Алгоритмічне та програмне забезпечення комп’ютерних систем»
Літня обчислювальна практика проводиться згідно з навчальним
планом спеціальності 122 – «Комп’ютерні науки» протягом 2 тижнів після
завершення літньої заліково-екзаменаційної сесії. Форма контролю – залік.
Студент, який вчасно не здав та не захистив обчислювальну практику,
вважається таким, що не виконав навчальний план і може бути відрахований
з університету за не виконання навчального плану.
Обчислювальна практика складається з 3-х частин: практична робота,
самостійна робота і захист практики.
Студенти працюють протягом 2 тижнів згідно з доведеним до них
графіком дистанційно з допомогою обраних викладачами-керівниками
практики платформ дистанційного навчання. Кожний студент одержує від
керівника практики завдання й опрацьовує його. Після підготовки він
захищає кожне завдання перед керівником практики, демонструє
працездатність програмного продукту та відповідає на запитання викладача
по завданню, оформлює звіт із обчислювальної практики і завантажує його
електронний варіант на вказаний керівником практики ресурс. При виконанні
вище наведених умов студент отримує залік.
Звіт із обчислювальної практики має наступну структуру:
- титульна сторінка;
- для кожного завдання:
постановка задачі;
програмна реалізація (код програми);
скріншоти роботи програми (введені дані та результат
виконання програми);
висновки.
2
Завдання на практику
Завдання №1. Рекурсивні підпрограми.
Мета роботи:
1. Засвоєння принципів організації рекурсивних процесів.
2. Практичні навички розроблення і використання рекурсивних
процедур та функцій.
Теоретичні відомості
Рекурсія – це такий спосіб організації обчислювального процесу, при
якому підпрограма під час виконання звертається сама до себе.
Програми, в яких використовуються рекурсивні процедури і функції,
відрізняються простотою і наочністю, але вони вимагають більше пам’яті і
виконуються, як правило, повільніше.
Виклик рекурсивної процедури або функції повинен здійснюватися за
умови, яка на деякому рівні рекурсії стає хибною і процес завершується,
інакше процес зациклюється, що зумовлює переповнення стека.
Рекурсивний виклик може бути прямим і непрямим. При непрямому
викликові підпрограма звертається до себе опосередковано як виклик з іншої
підпрограми.
Кількість вкладених викликів чи функції процедури називається
глибиною рекурсії. За допомогою рекурсивної програми можливо описати
нескінченне обчислення, причому без явних повторень частин програми.
n
xi x1 1, xi 0.3x i 1 ,
2. 1
i 1 yi
,
y1 1, y i xi21 y i 1 .
3
n
2k a1 1, a k 3bk 1 2a k 1 ,
3.
k 1 1 a k bk
,
b1 1, bk a k21 bk 1 .
n
a k bk a1 1, ak 0.3bk 1 0.2ak 1 ,
4. k 1! ,
k 1 b1 1, bk ak21 bk21.
n
xi x1 1, x 2 2, x 3 3,
5. k !! ,
i 1 xi xi 1 xi 2 xi 3 .
n
ak 1 1 1k .
6.
k 1 k 1!
, a k 1 1 1
2 ! 3! k 1!
n
ak 1 1 1 1 1 1 1 1
7. k 1 3k
, ak
2 1 2 2 2 3
2 k
.
n
1k 1 a , 1
sin 2 a k 1 1 .
8.
k 1 2k 1!
k a0 1 , ak 5
3k
n
1k 1 a sin 2 ak 1 1
9. k 1 k !!
k , a0 2 , ak
k2
.
k
n
1k
ak
10.
k m
,
k! 2
a0 1 , ak 4ak 1 2 .
3m n n 1 1
11. , 12. ,
m !!
1! 2! n !
um u 0 0 , u1 1,
13. ,
u m u m 1 u m 2 ,
n ! n 1! 1!
2m m!
14. 15. ,
1
1 1 1 1 1 1 1 1 1
1
3 1! 3 2 ! 3 3! 3 n! 3
1
1
2n 3
2n 1
4
m! m!
16. , 17.
2
m2 2 n 2 n 1 21
4
m2
2n 2
2n
m2 2
m
1, при n 0,
n i, при n 1,
18. H n, i , H n , i
i 1 2 iH n 1,i nH n 2, i ,
при n 1.
0, при i n,
n
i
i
19. C n , C 1,
n при i 0 або n i,
i 1 C i C i 1 , при n i .
n 1 n 1
n
i 1, при n 0,
20. An, i , An, i An 1,1, при i 0 , n 0,
i 1 An 1, An, i 1, при n 0, i 0 .
n
ai n
bi
23 i 1
24.
i 1
b1 b2 bi 1 1 1
ai a i 1 a1
n ai bi
25. i 1 ui
, u 0 0, u1 1, u n u n1 u n 2 .
5
Завдання №2. Динамічні структури даних.
Мета роботи:
Теоретичні відомості
Дані, які використовуються у програмі, поділяються на статичні й
динамічні.
Статичні структури даних розміщуються у статичній пам’яті,
виділеній компілятором у процесі компіляції програми. Їх взаєморозміщення,
взаємозв’язки елементів і кількість завжди залишаються сталими в процесі
виконання програми.
Динамічні структури даних розміщуються у динамічній пам’яті, яка
виділяється на етапі виконання програми. Їх внутрішня побудова формується
за деяким законом, а їх взаєморозміщення, взаємозв’язки елементів і
кількість можуть динамічно змінюватися в процесі виконання програми. Для
роботи з динамічними даними використовуються вказівники.
Вказівник – це статична змінна, значенням якої є адреса пам’яті. За
допомогою вказівників можна розміщувати в динамічній пам’яті будь-які
типи даних (цілі, дійсні, логічні, символьні, символьні рядки, масиви, записи
та інші). Такі вказівники називаються типізованими. Для опису типізованого
вказівника використовується знак ^, який записується перед відповідним
типом.
Під час роботи довільної програми значення деякої статичної змінної
може змінюватися, але власне кількість оголошених статичних змінних не
змінюється. Це не завжди зручно. Зручно використовувати структури в яких
кількість елементів може змінюватися.
6
Такі структури можна побудувати використовуючи динамічні змінні.
Динамічні змінні можна створювати під час роботи програми («на ходу») за
допомогою так званих змінних-вказівників.
1. Вказівники. Змінну-вказівник можна уявити як звичайну статичну
змінну, але таку, в якій зберігається не деяке конкретне значення наприклад
типу integer, real, …, а адрес іншої змінної.
1. Статична змінна має назву.
2. Динамічна змінна назви не має.
3. До статичної змінної можна звернутися по її назві.
4. До динамічної змінної – по її адресі (тобто по вказівнику, де ця адреса
знаходиться)
5. Змінна-вказівник може вказувати лише на динамічну змінну. І не може
вказувати на статичну.
Оскільки динамічна змінна не має імені (а отже не описується в блоці
var), то на початку роботи програми пам’ять під дану змінну не виділяється.
А відповідна змінна-вказівник ні нащо не вказує. Коли змінна-вказівник ні
нащо не вказує, то говорять, що вона вказує на nil.
Щоб виділити пам’ять, необхідно виконати процедуру new(x), де х –
змінна-вказівник.
Після виконання даної процедури (new(x)) вказівник x буде вказувати
на комірку пам’яті відповідного типу.
2. Списки. Зв'язаний список — одна з найважливіших структур даних,
в якій елементи лінійно впорядковані, але порядок визначається не номерами
елементів, а вказівниками, які входять в склад елементів списку та вказують
на наступний за даним елемент або на наступний та попередній елементи.
Зв'язані списки мають серію переваг порівняно з масивами. Зокрема, в
них набагато ефективніше виконуються процедури додавання та вилучення
елементів. Натомість, масиви набагато кращі в операціях, які потребують
безпосереднього доступу до кожного елементу, що у випадку зі зв'язаними
7
списками неможливо та потребує послідовного перебору усіх елементів, які
передують даному.
Застосування списків. Списки інтенсивно застосовуються в
програмуванні як самостійні структури. Також на їх основі можуть
будуватись більш складні структури даних, такі як дерева. На базі списків
також можуть бути реалізовані стеки та черги.
Переваги та недоліки. В загальному випадку, якщо необхідно
оперувати з динамічними множинами, де присутні інтенсивні операції з
додавання або видалення елементів, існують досить переконливі аргументи
для використання саме зв'язаних списків.
3. Стеки. Стек — різновид лінійного списку, структура даних, яка
працює за принципом «останнім прийшов — першим пішов» (LIFO, англ. last
in, first out). Всі операції (наприклад, видалення елементу) в стеку можна
проводити тільки з одним елементом, який знаходиться на верхівці стеку та
був введений в стек останнім.
Операції зі стеком:
* push ("заштовхнути елемент"): елемент додається в стек та
розміщується в його верхівці. Розмір стеку збільшується на одиницю. При
перевищенні розміру стека граничної величини, відбувається переповнення
стека
* pop ("виштовхнути елемент"): отримує елемент з верхівки стеку. При
цьому він видаляється зі стеку і його місце в верхівці стеку займає наступний
за ним відповідно до правила LIFO, а розмір стеку зменшується на одиницю.
При намаганні "виштовхнути" елемент з вже пустого стеку, відбувається
ситуація "незаповнення" стеку.
4. Черги. Черга — динамічна структура даних, що працює за
принципом "перший прийшов - перший пішов" (англ. FIFO — first in, first
out). У черги є голова (англ. head) та хвіст (англ. tail). Елемент, що додається
до черги, опиняється в її хвості. Елемент, що видаляється з черги,
знаходиться в її голові.
8
Основні операції з чергою
* "поставити в чергу". Операція додавання елемента в "хвіст" черги.
При цьому довжина черги збільшується на одиницю. Якщо відбувається
намагання додати елемент у вже заповнену чергу, відбувається її
переповнення
* "отримання з черги". Операція, яка повертає елемент з голови та
видаляє його з черги, таким чином встановлюючи голову на наступний за
видаленим елемент та зменшуючи довжину на одиницю. При намаганні
видалити елемент з пустої черги, виникає ситуація "незаповнення".
9
і дописує в кінець цього списку всі елементи в оберненому порядку до їх
розміщення в L (тобто будується симетричний список, наприклад,
1,2,3,3,2,1). Друкує отриманий список по сім елементів у рядку.
6. Розробити програму, яка створює список L , елементами якого є цілі числа.
Для заданих чисел a , b a b друкує в порядку розміщення всі числа списку
L менші від a , потім всі числа з діапазону a, b і, нарешті, всі числа більші
10
розміщені довільно). Вставляє елементи списку L 2 у L1 так, щоб L1
залишився упорядкованим. Друкує модифікований список L1 по десять
елементів у рядку.
13. Розробити програму, яка створює список L , елементами якого є малі
латинські літери. Друкує в алфавітному порядку всі літери, що входять у
список L по одному разу, по декілька разів і не входять жодного разу.
14. Розробити програму, яка створює список L , елементами якого є символи.
Вилучає із списку L всі повторні входження кожного символу. Друкує
модифікований список по п’ять елементів у рядку.
15. Розробити програму, яка створює списки L1 і L 2 , елементами яких є слова
із великих латинських літер. Знаходить всі слова списку L1 , що містяться в
L 2 , і друкує, розділюючи їх пробілами, в оберненому порядку до їх
розміщення.
11
Текстовий потік - це послідовність символів. При передачі символів з
потоку на екран, частина з них не виводиться (наприклад, символ повернення
каретки, переведення рядка).
Двійковий потік - це послідовність байтів, які однозначно відповідають
тому, що знаходиться на зовнішньому пристрої.
Організація роботи з файлами засобами C
Для організація роботи з файлами необхідно визначити вказівник на
файловий тип.
FILE * ідентифікатор;
Файл відкривається за допомогою fopen, яка повертає через вказівник
інформацію про потік введення-виведення, прикріпленого до зазначеного
файлу або іншого пристрою, з якого йде читання (або в який йде запис). У
разі невдачі функція повертає нульовий вказівник.
Схожа функція freopen бібліотеки Сі виконує аналогічну операцію
після першого закриття будь-якого відкритого потоку, пов'язаного з її
параметрами.
Вони визначаються як
FILE* fopen (const char * path, const char * mode);
FILE* freopen (const char * path, const char * mode, FILE * fp);
Ім’я та шлях розташування файлу передається в path. Режим доступу
(mode) - рядок, що вказує режим відкриття файлу файлу і тип файлу
Типи файлу: бінарний (b); текстовий (t). При відкритому файлі в
режимі відновлення ('+' в якості другого або третього символу аргументу
позначення режиму) і введення і виведення можуть виконуватися в одному
потоці.
Режим опис запис з …
12
r+ rb+ r+b відкриває для читання і запису початку
w+ wb+ w+b відкриває для читання і запису. Видаляє вміст і перезаписує файл. початку
a+ ab+ a+b відкриває для читання і запису (додає в разі існування файлу). кінця
13
Вхідна форма:
ФАЙЛ ім’я якого передається у
<let> <argv[1]>;
<рядок 1>
<рядок 2>
......
<рядок k>
......
Програми <argv[0]>
Пошук слів, що починаються з букви <let>
1 рядок: <рядок 1>
Знайдені слова: ФАЙЛ
<cлово 1> або < слова відсутні >
<argv[2]>;
<cлово 2>
....
2 рядок: <рядок 2>
Знайдені слова:
<cлово 1> або < слова відсутні >
<cлово 2>
....
і рядок: <рядок і>
Знайдені слова:
<cлово 1> або < слова відсутні >
<cлово 2>
....
Функціональний тест
let='s';
№ Досліджуваний текст Очікуваний результат: знайдені слова
рядка
14
Алгоритм
1. Відкриваємо файл з іменем <argv[1]> для читання, а файл з іменем
<argv[2]> для запису.
2. Якщо хоча б один файл не відривається виходимо з програми.
3. Записуємо у вихідний файл заголовок.
4. По рядках обробляємо файл, поки він не вичерпаний.
5. Записуємо у вихідний файл прочитаний рядок.
6. Виводимо шукані слова в міру знаходження.
7. Закриваємо файли та виходимо з програми.
Текст програми
#include<stdio.h>
#include<malloc.h>
#include<process.h>
#include<string.h>
const int lenmax=81; //типізована стала - границя масиву
int main(int argc, char* argv[])
{
char let,str[lenmax], *word;
FILE *dat,*res;
int k;
int len,l,wy,i,j;
//Відкриття файлів з перевіркою результатів відкриття
if((dat=fopen(argv[1],"r"))==NULL)
{ printf("Файл даних не відкритий"); return 1; }
if((res=fopen(argv[2],"w"))==NULL)
{ printf("Файл результату не відкритий"); return 1; }
//Вивід заголовків і введення let
fprintf(res,"Програма %s \n",argv[0]); // argv[0] - заголовок програми
fscanf(dat,"%c\n",&let); //не забувайте про &!
fprintf(res,"Пошук слів, що починаються з букви %c \n",let);
17
7. Задано текст, слова в якому розділені пробілами і розділовими знаками.
Розробити програму, яка вилучає з цього тексту всі повторні входження слів.