Вступ
Методичні вказівки для студентів напряму підготовки “Комп’ютерна інженерія” підготовлені з метою набуття практичних навиків під час розробки алгоритмів та написання програм на мові С, яка вивчається у навчальній дисципліні “Програмування”.
Основною метою виконання лабораторних робіт є:
опанування алгоритмічної мови програмування С;
набуття навичок в розробці алгоритмів методом покрокової деталізації на основі базових логічних структур;
вивчення та освоєння основних методів та прийомів програмування;
ознайомлення з процесом проходження завдань під час їх вирішення з використанням комп’ютерної системи;
отримання практичних навичок роботи в терміналі з відлагодження та тестування програм.
Структура лабораторних робіт включає мету роботи, короткі теоретичні відомості, методичні вказівки для підготовки до роботи та її виконання, індивідуальні завдання, контрольні запитання для підготовки до захисту.
Для захисту виконаної лабораторної роботи студенту необхідно підготувати звіт, який повинен включати:
титульний аркуш із зазначенням назви та теми лабораторної роботи (приклад його оформлення наведено у додатку А);
завдання до роботи;
блок-схеми алгоритму роботи програми;
лістинг програми;
результати роботи програми;
висновок, який включає в себе опис виконаної роботи із наведенням відповідей на питання: що зроблено, за допомогою чого це зроблено, які отримано результати, правильність отриманих результатів.
Завдання до кожної лабораторної роботи мають три рівні складності, яку кожен студент обирає на власний розсуд. Рівні складності визначають рівень можливої максимальної оцінки за виконувану роботу (“задовільно”, “добре”, “відмінно”).
Оцінка за роботу, оформлену належним чином, виставляється відповідно до рівня виконаного завдання.
Лабораторна
робота 1 Лінійні алгоритми
Мета: вивчити структуру програми мови С; навчитись працювати з середовищем програмування сімейства MS Visual Studio; ознайомитися з операторами введення–виведення; отримати навички з використання у програмі простих типів даних, складання найпростіших блок-схем програм та програм мовою С.
Короткі теоретичні відомості
1.1. Знайомство з середовищем програмування MS Visual Studio 2013. Програма, яка створюється в середовищі MS Visual Studio, організована у вигляді проекту. Проект – це набір взаємопов’язаних вихідних файлів, призначених для розв’язання певної задачі. До складу проекту входять файли, створені програмістом, а також файли, які створюються середовищем програмування автоматично. Компіляція та компоновка файлів проекту дозволяє отримати виконувану програму. Одночасно зі створенням проекту середовище MS Visual Studio створює рішення (solution) як засіб об’єднання декількох проектів для більш зручної роботи з ними.
Середовище програмування MS Visual Studio підтримує роботу з декількома мовами програмування та програмними платформами, тому перед початком написання програми на мові С необхідно виконати наступні підготовчі кроки по створенню проекту.
Для створення нового проекту потрібно виконати кроки:
запустити MS Visual Studio 2013. Після запуску Visual Studio 2013 з’явиться стартове вікно, зображене на рис. 1.1. Обрати пункт головного меню FileNew®Project (або натиснути комбінацію клавіш Ctrl + Shift + N), як показано на рис. 1.2;
у вікні New Project розгорнути вузол Visual С++, обрати пуннкт Win32, на центральній панелі обрати тип створюваного проекту Win32 Console Application, як відображено на рис. 1.3;
в поле Name ввести ім’я проекту, наприклад lab1;
в полі Location ввести ім’я каталогу, в якому буде розміщено проект, та повний шлях до нього, наприклад D:\student\. Каталог може бути обрано також у діалоговому вікні Project Location, що може бути відкритим за допомогою кнопки Browse…;
натиснути на кнопку OK;
Рис. 1.1
Рис. 1.2
Рис. 1.3
у вікні майстра створення додатків Win32 Application Wizard (після натискання на кнопку Next) в додаткових опціях (Additional options) обрати опцію Empty project, як показано на рис. 1.4, та натиснути на кнопку Finish.
Для додавання до проекту файлу, в якому буде створено вихідний код, у вікні Solution Explorer (оглядач рішень) виконати наступні дії, як відображено на рис. 1.5:
натиснути правою кнопкою миші на папці Source Files (вузол lab1) та обрати з контекстного меню, що з’явилося, AddNew Item (новий елемент);
у вікні Add New Item обрати пункт меню Code вузла Visual C++, в центральній частині панелі обрати тип файлу C++ File (.cpp). В полі Name задати ім'я файлу, наприклад main.c, де розширення .c вказує на те, що файл містить код на мові С, як показано на рис. 1.6;
натиснути на кнопку Add.
Доданий файл буде відображено в дереві Solution Explorer (вузол Source Files, файли з вихідним кодом). Для створеного файлу автоматично відкривається редактор коду, вікно якого зображено на рис. 1.7.
Рис. 1.4
Рис. 1.5
Рис. 1.6
Рис. 1.7
Для налаштування проекту потрібно виконати наступні кроки:
обрати пункт головного меню Projectlab1 Properties, як показано на рис. 1.8;
у списку вузла С/С++ обрати пункт Advanced, в правій частині панелі властивість Compile As встановити у Compile as C Code (/TC), як показано на рис. 1.9;
натиснути на кнопки Применить та OK.
Рис. 1.8
Рис. 1.9
У вікні Solution Explorer відображено папки, в яких містяться файли проекту:
папка External Dependencies містить файли, які не було додано до проекту, проте які використовуються в файлах вихідного коду (наприклад, додані за допомогою директиви #include);
папка Header Files містить заголовкові файли з розширенням .h;
папка Resource Files містить файли ресурсів (зображення тощо);
папка Source Files містить файли з вихідним кодом (в даному проекті – файли з розширенням .с).
Для створення файла виконуваної програми, потрібно обрати пункт меню BuildBuild Solution. Для запуску програми потрібно обрати пункт меню DebugStart Without Debugging (запуск без налагодження), або натиснути комбінацію клавіш Ctrl+F5.
1.2. Структура програми на мові С. Програма, написана на мові С, обов’язково містить головну функцію main(), з якої починається виконання програми. Також програма може містити функції, визначені програмістом. Головна функція повинна відображати схему роботи програми. Найчастіше вона містить виклики інших функцій. Загальна структура програми на мові С подана нижче, де f1() — fN() є функціями, які написані програмістом.
Загальна структура програми на мові С
Оголошення глобальних змінних тип_значення_що_повертається main(список параметрів) { послідовність операторів } тип_значення_що_повертається f1(список параметрів) { послідовність операторів } тип_значення_що_повертається f2(список параметрів) { послідовність операторів } . . . тип_значення_що_повертається fN(список параметрів) { послідовність операторів } |
|
Головна функція може мати наступні варіанти запису:
int main()
{
тіло функції з командою
return 0;
}
або
void main()
{
тіло функції;
}
У першому варіанті запису функція починається з цілого типу int та імені. В другому варіанті функція починається з “порожнього” типу void, який означає, що функція не буде повертати жодного значення. Функція в обох прикладах не має параметрів, тому за її ім’ям розташовуються порожні круглі дужки (). Тіло функції, яке записується в фігурних дужках {}, містить команди та виклики інших функцій. Команди відокремлюються одна від одної символом «;». Оператор повернення з функції return перериває виконання функції, і в першому прикладі він повертає певне ціле значення (нульове значення в разі успішного завершення програми, ненульове – у разі помилки в програмі).
1.3. Директиви препроцесора. Директиви препроцесора – це інструкції для компілятора, які розширюють можливості середовища програмування. Всі директиви препроцесора починаються зі знаку #, кожна директива має бути написана в окремому рядку.
Наприклад, директива #include надає вказівку компілятору приєднати до програми програмний код із зазначеного файлу. Такі файли називають файлами заголовків (header-файлами, бібліотеками або модулями). Ім’я заголовкового файлу повинно бути взятим в подвійні лапки або кутові дужки. Наприклад:
#include <назва_файлу.розширення>
#include "назва_файлу.розширення"
Якщо ім’я файла міститься у кутових дужках, то пошук файла здійснюється у спеціальному каталозі файлів для включення (зазвичай каталог INCLUDE). Якщо ім’я файла взяте у подвійні лапки, то пошук файла ведеться у поточній директорії активного диска. Якщо пошук буде невдалим, то він продовжується у спеціальному каталозі для header-файлів. Другий спосіб зазвичай використовується для підключення власно створених файлів.
1.4. Коментарі. Коментар – це фрагмент тексту програми, який пояснює призначення частини коду чи програми і не впливає на виконання команд. Багаторядковий коментар повинен починатись з символів /* і закінчуватись символами */, наприклад:
/* це
багаторядковий
коментар */
Однорядковий коментар починається з символів // та закінчується в кінці рядка, наприклад:
// це однорядковий коментар
1.5. Типи даних. Стандарт С89 визначає п’ять основних типів даних, на основі яких утворюються інші типи: char – символьні, int – цілі, float – з плаваючою крапкою, double – з плаваючою крапкою подвійної точності, void – без значення. Обсяг пам’яті, який займається даним певного типу, та діапазон значень цих типів даних можуть бути різними для різних процесорів та компіляторів.
Базові типи даних, за виключенням void, можуть мати модифікатори: signed, unsigned, long, short. Модифікатор unsigned вказує на те, що дане приймає невід’ємні значення. Модифікатор signed вказує на те, що дане може приймати як додатні, так і від’ємні значення. В таблиці 1.1 наведено можливі комбінації типів даних мови С, їх мінімальні діапазони та розмір в бітах.
Таблиця 1.1 – Типи даних мови C
Тип |
Розмір в бітах |
Мінімальний діапазон |
char |
8 |
від -127 до 127 |
unsigned char |
8 |
від 0 до 255 |
signed char |
8 |
від -127 до 127 |
int |
16 або 32 |
від -32767 до 32767 |
unsigned int |
16 або 32 |
від 0 до 65535 |
signed int |
16 або 32 |
такий самий, як у int |
short int |
16 |
від -32767 до 32767 |
unsigned short int |
16 |
від 0 до 65535 |
signed short int |
16 |
такий самий, як у short int |
long int |
32 |
від -2 147 483 647 до 2 147 483 647 |
long long int |
64 |
від -(263-1) до (263-1), доданий стандартом C99 |
signed long int |
32 |
такий самий, як у long int |
unsigned long int |
32 |
від 0 до 4 294 967 295 |
unsigned long long int |
64 |
від 0 до (264-1), доданий стандартом C99 |
float |
32 |
від 1E-37 до 1E+37, з точністю не менше 6 значущих десяткових цифр |
double |
64 |
від 1E-37 до 1E+37, з точністю не менше 10 значущих десяткових цифр |
long double |
80 |
від 1E-37 до 1E+37, з точністю не менше 10 значущих десяткових цифр |
Символьний тип char – це множина символів кодової таблиці комп'ютера ASCII. Символьна стала – це один символ, взятий в лапки, або число у вісімковій, десятковій чи шістнадцятковій системі числення, яке є кодом символу у таблиці ASCII.
Наприклад:
char let1 = 'A', let2 = 0101, let3 = 65, let4 = 0x41;
В цьому прикладі змінні let1, let2, let3 та let4 отримали значення латинської літери 'A', оскільки 65, 101 та 41 – відповідно десятковий, вісімковий і шістнадцятковий коди символу 'A' (на початку вісімкового та шістнадцяткового кодів додаються префікси '0' та '0х' відповідно).
Приклад визначення десяткового ASCII-коду символу:
char let = 'A';
int c = let;
В результаті змінна с отримає значення 65.
Якщо специфікатор типу записати без наступного за ним базового типу, то передбачається, що він модифікує тип int, наприклад, специфікатори типів unsigned int та unsigned еквівалентні.
Базовий тип int за стандартом С89 передбачається за замовчуванням, тобто якщо явний специфікатор типу відсутній, то мається на увазі тип int. В стандарті С99 правила присвоєння типу за замовчуванням немає, він вимагає явного вказування типу int.
Для цілого типу можна використовувати специфікатор signed, проте при оголошенні цілого він передбачається за замовчуванням.
Тип void слугує, наприклад, для оголошення функції, яка не повертає значення. Цей тип буде розглянуто пізніше.
Перетворення типів. Якщо операнди мають різні типи, результат операції перетворюється до старшого типу:
char та short перетворюються до int;
float – на double;
якщо один з операндів long double, то результат перетворюється до long double;
якщо один з операндів long, то результат перетворюється до long;
якщо один з операндів unsigned, результат перетворюється до unsigned.
Явне перетворення типу використовується для примусового перетворення значення одного типу даних до іншого і має наступний синтаксис:
(новий_тип) вираз;
Наприклад:
int a;
int b = 10;
char c = 50;
a = (int)c * 2 - b; // змінна c перетворюється до типу int.
1.6. Змінні. Змінна – це іменована ділянка пам’яті, в якій зберігається значення, що може бути змінено програмою. В мові С імена змінних, функцій тощо називаються ідентифікаторами. Ідентифікатор є послідовністю з одного або декількох символів. Першим символом ідентифікатора може бути літера або символ підкреслення, наступні символи можуть бути літерами, цифрами або символами підкреслення. Верхні та нижні регістри символів розглядаються як різні, тобто number, Number та NUMBER є різними ідентифікаторами.
В мові С довжина ідентифікатора може бути будь-якою, проте не всі його символи будуть значущими. У стандарті С89 значущими є як мінімум перші 6 символів зовнішнього імені і перші 31 символ внутрішнього імені. Для стандарту С99 значущими є для зовнішнього ідентифікатора перші 31 символ, а для внутрішнього – перші 63 символи. За стандартом С11 кількість значущих символів ідентифікаторів визначається реалізацією компілятора.
Примітка. Зовнішні ідентифікатори (зовнішні імена) беруть участь у зовнішньому процесі компонування та позначають імена функцій і глобальних змінних, які використовуються спільно в різних вихідних файлах. Якщо ідентифікатор не бере участь в процесі редагування зовнішніх посилань, то він називається внутрішнім ім'ям. До таких імен належать, наприклад, імена локальних змінних.
Перед використанням всі змінні повинні бути оголошені за наступною загальною формою:
тип список_змінних;
Приклади оголошень:
int c, n, k;
short int ch;
unsigned int y;
double expense;
Змінні можуть бути оголошені всередині функції (локальні змінні), у визначенні параметрів функції (формальні параметри функції) та поза межами всіх функцій (глобальні змінні). Локальна змінна може бути використана лише всередині блоку, в якому її оголошено (блок програми – це описи та інстрцукції, взяті в фігурні дужки {}). Глобальні змінні можуть використовуватись в будь-якому місці програми. Формальні параметри функції – це змінні, які приймають значення аргументів функції.
Змінні можна ініціалізувати, тобто присвоювати їм початкові значення, у місці їх опису, наприклад:
int length = 45;
float diameter = 120.25;
сhar letter = ’a’;
Кваліфікатор const. Змінна, до якої в оголошенні застосовано кваліфікатор const, не може змінювати своє значення.
Наприклад:
const int a = 100;
Тут змінна a може бути використана у виразах, проте її значення змінити не можна.
1.7. Вирази. Вираз складається з знаків операцій та операндів. Операндом може бути константа, змінна або ім’я функції.
Арифметичні операції. Арифметичні операції мови С наведено в таблиці 1.2. Більшість операцій використовують два операнди, один з яких розташовується перед знаком операції, а другий – після (наприклад, операція додавання). Такі операції називаються бінарними. Унарні операції використовують лише один операнд (наприклад, унарний мінус). В мові С визначено також операцію, яка має три операнди (тернарну операцію) – операція ?:.
Таблиця 1.2 – Арифметичні операції мови С
Операція |
Зміст операції |
- |
Віднімання, також унарний мінус |
+ |
Додавання |
* |
Множення |
/ |
Ділення |
% |
Остача від ділення (ділення за модулем) |
-- |
Декремент, зменшення |
++ |
Інкремент, збільшення |
Операції додавання (+) та віднімання (–) можуть застосовуватись до цілих та дійсних чисел. В операціях множення (*) та ділення (/) операнди можуть бути будь-яких арифметичних типів. Якщо операція ділення (/) застосовується до цілого або символьного типів, то остача від ділення відкидається. Операція остача від ділення (%) застосовується лише до цілих операндів. Операція унарний мінус змінює знак операнда на протилежний. Приклади виконання операцій ділення та остачі від ділення:
int x, y;
x = 5;
y = 2;
printf("%d ", x/y); /* результат 2 */
printf("%d ", x%y); /* результат 1*/
x = 1;
y = 2;
printf("%d %d", x/y, x%y); /* результат 0 1 */
Примітка. Функція printf(), яку буде розглянуто пізніше, здійснює виведення даних на консоль.
Операція декременту (--) зменшує значення операнда на 1, операція інкременту (++) збільшує значення операнда на 1. Операції інкременту та декременту існують в двох формах – префіксній (коли знак операції інкременту або декременту записаний перед операндом) та постфіксній (коли знак операції інкременту або декременту записаний після операнду). Таким чином, вираз
x = x+1;
може бути записаний в еквівалентній формі:
++x; або x++;
Аналогічно рівносильними є записи x = x-1; та --x або x--;.
Якщо знак операції інкременту (декременту) записаний у префіксній формі, то операція виконується до використання результату у виразі. Якщо у постфіксній, то у виразі використовується значення операнда до виконання операції інкременту (декременту).
Наприклад, результати виконання команди
x = 10;
y = ++x;
будуть такими: y = 11, x = 11.
Якщо ж використати постфіксну форму запису
x = 10;
y = x++;
то результати будуть наступними: y = 10, x = 11.
Пріоритет виконання арифметичних операцій. Пріоритет виконання арифметичних операцій наведено в таблиці 1.3. Операції, які мають однаковий пріоритет, виконуються зліва направо. Порядок обчислення може бути змінено шляхом використання круглих дужок, які надають операції або послідовності операцій найвищий пріоритет.
Таблиця 1.3 – Пріоритет виконання арифметичних операцій
Пріоритет |
Операція |
Найвищий |
++, -- |
- (унарний мінус) |
|
*, /, % |
|
Найнижчий |
+, - |
Операція присвоєння. Загальна форма операції присвоєння наступна:
ім'я_змінної = вираз;
Вираз може бути константою або комбінацією складних операторів. Адресатом (ліва частина операції присвоєння) має бути об’єкт, здатний отримувати значення (наприклад, змінна, проте не функція і не константа).
Якщо у виразі використовуються змінні різних типів, здійснюється перетворення типів. Для операції присвоєння в такому випадку значення правої частини перетворюється до типу лівої частини.
Множинні присвоєння. Операція множинного присвоєння використовується для присвоєння одного й того самого значення багатьом змінним, наприклад:
x = y = z = 0;
Наступний приклад демонструє використання таких присвоєнь:
#include<stdio.h>
void main()
{
int data1, data2, data3;
data1 = data2 = data3 = 100;
printf("\ndata1==%d\ndata2==%d\ndata3==%d", data1, data2, data3);
}
Результат:
data1==100
data2==100
data3==100
Присвоєння відбувається справа наліво: спочатку зміна data3 отримує значення 100, потім зміна datа2 і нарешті data1.
В мові С також допускаються присвоєння виду:
a = (b = c = 1) + 1;
Використання таких присвоєнь демонструє наступний приклад:
#include<stdio.h>
void main()
{
int a, b, c;
a = (b = c = 1) + 1;
printf("%d %d %d", a, b, c);//результат 2 1 1
}
Складені операції присвоєння. Для скорочення написання запису використовується складене присвоєння. Складені операції присвоєння існують для всіх бінарних операцій. Будь-яка операція вигляду
змінна = змінна знак_операції вираз;
може бути записана у формі:
змінна знак_операції = вираз;
Наприклад, запис
x = x+10;
може бути поданий у формі:
x += 10;
Операції порівняння та логічні операції. Операції порівняння та логічні операції, визначені в мові С, наведено в таблиці 1.4. В якості операндів та результатів цих операцій використовується значення ІСТИНА (true) та ХИБНІСТЬ (false). В мові С значення ХИБНІСТЬ представлене нулем, а ІСТИНА – будь-яким числом, відмінним від нуля. В стандарті С99 додатково визначено цілий тип даних _Bool, який може зберігати значення 1 (true) та 0 (false). Також стандарт С99 додає заголовковий файл <stdbool.h>, в якому визначено імена макросів bool, true та false.
Приклад запису:
bool f = true;
Операції порівняння зазвичай використовуються в умовних виразах. Логічні операції &&, ||, ! зазвичай використовуються для об’єднання виразів порівняння. Наприклад, (A<=B)&&(B!=C).
Таблицю істинності логічних операцій мови С подано в таблиці 1.5.
Таблиця 1.4 – Операції порівняння та логічні операції, визначені в мові С
Операції порівняння |
|
Операція |
Зміст операції |
> |
Більше ніж |
>= |
Більше або дорівнює |
< |
Менше ніж |
<= |
Менше або дорівнює |
== |
Дорівнює |
!= |
Не дорівнює |
Логічні операції |
|
Операція |
Зміст операції |
&& |
І |
|| |
АБО |
! |
НІ, заперечення |
Таблиця 1.5 – Таблиця істинності логічних операцій мови С
A |
B |
A&&B |
A||B |
!A |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
Операція sizeof()обчислює розмір пам’яті, необхідний для розміщення виразів або змінних вказаних типів. Операцію sizeof() можна застосовувати до констант, типів та змінних. Результатом є число байт, що відводяться під операнд.
Операція використовується в двох формах:
ім’я_типу А; sizeof А;
або
sizeof (ім’я_типу);
Наприклад, визначимо число байт, необхідних для розміщення змінної типу int:
sizеof(int);
Математичні функції. Основні математичні функції мови С подано в таблиці 1.6. Для забезпечення можливості використання цих функцій до коду програми має бути підключено заголовковий файл <math.h>. Всі функції, які приймають або повертають значення кута, працюють з радіанами.
Таблиця 1.6 – Основні математичні функції мови С
Ім'я |
Опис |
acos |
арккосинус |
asin |
арксинус |
atan |
арктангенс |
ceil |
округлення до найближчого більшого цілого числа |
cos |
косинус |
exp |
показникова функція |
fabs |
абсолютне значення |
floor |
округлення до найближчого меншого цілого числа |
fmod |
повертає залишок від ділення двох чисел |
log |
натуральний логарифм |
log10 |
десятковий логарифм |
modf(x, p) |
повертає цілу та дробову частину аргументу х зі знаком |
pow(x,y) |
обчислює значення xy |
sin |
синус |
sqrt |
квадратний корінь |
tan |
тангенс |
За стандартом С89 аргументами математичних функцій повинні бути значення типу double, причому значення, що повертаються функціями, теж мають тип double. Стандартом С99 додані варіанти цих функцій, що працюють з типами float і long double. У цих функціях використовуються суфікси f та l відповідно (наприклад, для функції sin() – це модифікації sinf() та sinl()).
Всі інші математичні функції можна виразити через основні, наприклад, ctg х = 1 / tg x тощо.
