Оператор безумовного переходу

МЕТА РОБОТИ

Мета роботи – навчитися програмувати на мові С++ розгалужені обчислювальні процеси.

2. ТЕОРЕТИЧНІ ВІДОМОСТІ

Алгоритми

Вивчаючи основи програмування потрібно освоїти не лише одну з мов програмування високого рівня, а й навчитися складати та аналізувати алгоритми розв’язку різних задач, і таким чином, виробити алгоритмічне мислення.

Поняття алгоритму є одним з фундаментальних понять в комп’ютерних науках. Воно виникло задовго до появи перших комп’ютерів і стало одним з основних у математиці. Вважається, що саме слово “алгоритм” походить від імені видатного математика середньовіччя Мухаммеда бен-Муси аль-Хорезмі. Він розробив алгоритм (правила) виконання арифметичих дій над десятковими числами, яким ми користуємось до сих пір. Тепер слово “алгоритм” використовується не тільки в математиці, так говорять про алгоритм гри у шахи, алгоритм керування різними процесами тощо.

Для розуміння поняття “алгоритм” та його ролі в програмуванні не обов’язково застосовувати строго математичний формалізм, достатньо дати тлумачення цього поняття на “інтуїтивному” рівні. Тут, в першу чергу, слід відзначити важливе значення поняття “виконавець алгоритму”. Алгоритм завжди повинен бути сформульованим у розрахунку на конкретного виконавця, тобто він має бути керівництвом до дій для виконавця. Саме тому, значення слова “алгоритм” є схожим за змістом до значення слів “вказівка”, “інструкція”. Можна стверджувати, що алгоритм – це зрозумілі й точні вказівки виконавцю (комп’ютеру) здійснити певну послідовність дій (обчислювальних операцій) для розв’язання поставленої задачі.

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

Ø словесний запис алгоритму (розмовна мова);

Ø псевдокод (структурно-стилізована мова);

Ø блок-схема (мова графічних символів);

Ø комп’ютерна програма (мова програмування високого рівня).

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

Наступним кроком у напрямку підвищення рівня формалізації опису алгоритму є використання так званого псевдокоду. Псевдокод – це система позначень і правил, призначена для одноманітного запису алгоритмів. У псевдокоді відсутні строгі синтаксичні правила для запису команд, тому програма на псевдокоді не може виконуватися комп’ютером. Його призначення – допомогти розробнику “осмислити” програму перед тим як спробувати її написати мовою програмування такою як С++. А завдяки наявності конструкцій, які притаманні мовам програмування, значно полегшується перехід від детально підготовленої програми на псевдокоді до програми написаної мовою С++.

На одному рівні формалізації опису алгоритму поряд з псевдокодом знаходиться графічна форма опису у вигляді блок-схеми. Основною перевагою блок-схем над псевдокодом є більша наочність подання алгоритму. Але для великих алгоритмів ця перевага втрачається. В блок-схемах для позначення алгоритму використовуються спеціальні символи у вигляді найпрос­тіших геометричних фігур, які називаються блоками. Блоки з’єднуються за допомогою стрілок, які називаються лініями зв’язку і які вказують на черговість виконання. Самі команди поміщаються усередину блоків і можуть набувати, взагалі кажучи, довільної форми, наприклад, задаватися словами (хоча в такому випадку формалізація опису зменшуються). Блок-схеми можуть використовуватися як для опису повного алгоритму, так і для опису деякого фрагменту алгоритма. У першому випадку блок-схема повинна починатися з блоку у вигляді овалу з написом Початок і завершуватися також овалом тільки вже з написом Кінець. У другому випадку будемо починати і завершувати блок-схему символом маленького кола без напису, який називається блоком з’єднання (злиття). Для позначення всіх можливих елементарних дій на блок-схемах будемо використовувати блок у вигляді прямокутника, який називатимемо блоком обробки інформації або блоком виконання дій. Цей блок повинен мати один вхід, заданий стрілкою, яка входить в блок зверху або збоку, і один вихід, заданий стрілкою, що виходить з блоку донизу (також можливо у бік). І нарешті, блок у вигляді ромба, який називається логічним блоком, буде використовуватися для перевірки умов і вибору напрямку виконання алгоритму залежно від умови. Сама умова записуються усередині ромба. Аналогічно, вхід та вихід позначаються стрілками, але на відміну від блоку виконання дій, логічний блок завжди має один вхід та два виходи. Описані блоки та інші блоки, які будуть використовуватися нами для побудови блок-схем наведено у табл.1.

Таблиця 1. Мова графічних символів

Назва символу Позначення Пояснення
Блок виконання дій Оператор безумовного переходу - student2.ru Обчислювальна дія або послідовність обчислювальних дій
Логічний блок Оператор безумовного переходу - student2.ru Перевірка умови
Блок модифікації Оператор безумовного переходу - student2.ru Початок циклу з параметром
Блок виклику функції Оператор безумовного переходу - student2.ru Виклик підпрограми
Блок з’єднання Оператор безумовного переходу - student2.ru Об’єднання ліній потоку
Блок початку/кінця Оператор безумовного переходу - student2.ru Початок і закінчення алгоритму

З певних комбінацій блоку виконання дій та логічного блоку створюються керуючі структури або базові конструкції алгоритмів. В теорії алгоритмів доведено, що будь-який алгоритм може бути побудований з використанням всього лише трьох базових конструкцій, а саме з конструкцій слідування, розгалуження та повторення. Це перетворює процес побудови алгоритму в його “збірку” з набору базових конструкцій. Блок-схеми керуючих структур можна розглядати як блок-схеми фрагментів алгоритму, тобто вони починатимуться з блоку злиття, який буде відігравати роль точки входу в структуру і закінчуватися також цим блоком, який буде точкою виходу з структури. Таке трактування керуючих структур з одним входом і одним виходом значно полегшує процес побудови алгоритму шляхом збирання з базових конструкцій – керуючі структури зв’язуються послідовно шляхом з’єднання точки виходу однієї з них з точкою входу іншої. Іншим способом збирання цілого алгоритму з базових конструкцій є вкладення однієї керуючої структури в іншу. Його ми розглянемо детально пізніше.

Під час запису алгоритму у словесній формі, у вигляді блок-схеми чи на псевдокоді допускається певна довільність в записі команд. На практиці як виконавець алгоритмів використовують комп’ютер, тому алгоритм має бути записаний мовою “зрозумілою” комп’ютером. Тут на перший план виступає необхідність точного запису команд, яка не залишає місця для довільного тлумачення їх виконавцем. Тому мова для запису алгоритму має бути строго формалізована – вона називається мовою програмування, а форма алгоритму цією мовою – комп’ютерною програмою або просто програмою.

Отже, будь-який алгоритм може бути побудований з використанням всього лише трьох базових конструкцій, а саме конструкцій слідування, розгалуження та повторення. Структура слідування вбудована в мові С++. Це означає, що оператори програми виконуються один за одним в тій послідовності, в якій вони записані у тексті програми, поки не буде вказано інший порядок виконання.

Організація розгалуження в С++ здійснюється за допомогою трьох типів програмних структур вибору: оператора умови ifз одиничним вибором, оператора умови if/else з подвійним вибором і оператора вибору switch з множинним вибором. Конструкція повторення реалізується в С++ за допомогою трьох операторів циклу: оператора циклу з передумовою while, оператора циклу з післяумовою do/while і оператора циклу з параметром for. І це все. Мова С++ має лише сім керуючих структур: слідування, три типи вибору і три типи повторення. Довільна програма мовою С++ формується з такої кількості комбінацій кожного типу керуючих структур, яка потрібна для реалізації відповідного алгоритму.

2.2. Оператори умови в мові С++

Оператор if виконує певну дію, якщо умова вибору є істинною, і пропускає виконання цієї дії, якщо умова є хибною. Синтаксичний опис оператора умови з одиничним вибором такий:

if (<умова>) <оператор>;

Спочатку обчислюється <умова>, яка синтаксично задається у вигляді виразу, резуль­татом виконання якого є або ненульове значення (означає, що умова є істинною або умова виконується), або значення 0 (означає, що умова є хибною або умова не виконується). У мові С++ відсутній спеціальний логічний тип, якому відповідають значення типу TRUE і FALSE (як у мові Паскаль). Аналогом значення TRUE у С++ є будь-яке ненульове значення, а значення FALSE – 0. Таким чином, виконання оператора if полягає в наступному: якщо <умова> є істинною, то виконується <оператор>, якщо <умова> є хибною, то оператор заданий після умови виконуватися не буде, а програма продовжить своє виконання з наступного після if оператора.

Трактування умови в операторі if як звичайного виразу, дозволяє створювати в С++ умови виконання, які не обов’язково повинні містити операції, що за своєю логікою виконання завжди дають лише два можливих значення, як наприклад, операції порівняння. Ці операції, як відомо, дають результат 1, якщо відношення, задане операцією порівняння дійсно має місце, і результат 0 у протилежному випадку. Для прикладу, поекспериментуйте з наведеною нижче програмою, задаючи різні вхідні значення (додатнє, від’ємне, нульове) для змінної n. Зверніть увагу на те, в яких випадках виводиться на екран той чи інший текст і спробуйте пояснити чому. Також, додайте відповідні оператори виведення для перевірки результату виконання інших операцій порівняння.

#include <iostream>

#include <conio.h>

void main()

{

using namespace std;

int n;

cout<<"Enter n:";

cin>>n;

if (n) cout<<"TRUE"<<endl; // така умова в С++ є коректною!

if (n>0) cout<<"n is positive"<<endl;

if (n<0) cout<<"n is negative"<<endl;

if (n==0) cout<<"n is zero"<<endl;

cout<<"Value of operation > is "<<(n>0)<<endl;

cout<<"Value of operation < is "<<(n<0)<<endl;

cout<<"Value of operation == is "<<(n==0)<<endl;

_getch();

}

Для вибору однієї із двох можливих дій, в залежності від значення певної умови, використовується оператор умови if/else, який має таку синтаксичну структуру:

if (<умова>) <оператор1>; else <оператор2>;

Аналогічно до попереднього випадку, спочатку обчислюється <умова>, і якщо вона є істинною (має ненульове значення), то виконується <оператор1>, а якщо умова є хибною (має нульове значення), то виконується <оператор2>. Блок-схеми на рис.1 наочно демонструють логіку роботи обох операторів умови.

Оператор безумовного переходу - student2.ru

Рис.1. Керуюча логіка операторів if мови С++

У ролі <оператор1> та <оператор2> може бути будь-який допустимий оператор мови С++, в тому числі й сам оператор умови. У такому випадку отримуємо вкладені структури if/else, які дозволяють реалізувати розгалуження обчислювального процесу більше ніж у двох напрямках. Тут слід пам’ятати, що кожне службове слово else відноситься до першого перед ним слова if. Так, наприклад, при заданих початкових значеннях x=1; y=-1, після виконання оператора

if (x>0) if (y>0) z=1; else z=2;

змінна z буде мати значення 2. Якщо ми хочемо, щоб гілка else z=2; відносилася не до умови if (y>0), а до if (x>0), то треба цей оператор записати так:

if (x>0) {if (y>0) z=1;} else z=2;

За правилами мови С++ <оператор1> та <оператор2> мають бути структурно одним єдиним оператором. Якщо користувачеві необхідно виконати в цих місцях кілька операторів, то їх треба взяти в операторні дужки { }, тобто зробити ці декілька операторів складеним оператором. Складений оператор вживається у програмі завжди, якщо за синтаксисом мови С++ наступний оператор може бути тільки єдиним, а користувачеві потрібно виконати певну послідовність операторів. Складений оператор має таку структуру:

{ <оператор1>; <оператор2>; ... <операторN> }

У ролі прикладу використання складеного оператора в структурі if/else, розглянемо задачу обчислення виразу Оператор безумовного переходу - student2.ru з врахуванням обмеження на область визначення функції квадратного кореня.

#include <iostream>

#include <conio.h>

#include <math.h>

void main()

{

using namespace std;

double x,y;

cout<<"Введіть значення x:"<<endl;

cin>>x;

if (x<0)

cout<<"При х<0 обчислення виразу неможливе!"<<endl;

else {

y=0.75*sqrt(x)-0.5*pow(4, 1.0/3);

cout<<"y="<<y<<endl;

}

_getch();

}

2.3. Логічні операції та умовна операція ?:

Іншим типом операцій в мові С++, які завжди мають результат типу ‘істина’/’не істина’ є логічні операції. Цих операцій в С++ є три: операція логічного множення && (логічне І), операція логічного додавання || (логічне АБО) та операція логічного заперечення ! (логічне НЕ). Операції логічного множення і додавання працюють так, як показано у табл.2.

Таблиця 2. Логічне множення і логічне додавання

&& не нуль   || не нуль
 
не нуль   не нуль

Логіка операції логічного заперечення така: !0=1 та !1=0.

За допомогою логічних операцій та операцій порівняння можна утворювати складні вирази для запису умови в операторі if/else. Наприклад, перевірка чи значення змінної x лежить в діапазоні від а до b може бути задана у вигляді такої умови:

(x>=a && x<=b)

Мова С++ має також умовну операцію ?:, яка є схожою на структуру if/else. Ця умовна операція є єдиною тернарною операцією, тобто такою, що має три операнда. Ці операнди разом з самою умовною операцією утворюють умовний вираз, який має такий вигляд:

<умова> ? <вираз1> : <вираз2>.

Тут, перший операнд є умовою, другий операнд містить значення умовного виразу в тому випадку, якщо умова є істинною, а третій операнд рівний значенню умовного виразу, якщо умова є хибною. Наприклад, оператор виведення

cout<< (grade>=50 ? “ЗДАВ” : “НЕ ЗДАВ”);

містить умовний вираз, значення якого рівне рядку “ЗДАВ”, якщо умова grade>=50 виконується, і рівне рядку “НЕ ЗДАВ”, якщо ця умова не виконується. Таким чином, цей оператор з умовною операцією виконує фактично ті ж дії, що і аналогічний оператор if/else:

if(grade>=50)cout<<“ЗДАВ”; else cout<<“НЕ ЗДАВ”;

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

Значенням умовного виразу можуть також бути певні дії. Наприклад, умовний вираз

grade>=50 ? cout<<“ЗДАВ” : cout<<“НЕ ЗДАВ”;

може бути прочитаний так: “Якщо оцінка grade більша або рівна 50, то вивести повідомлення ‘ЗДАВ’, інакше вивести повідомлення ‘НЕ ЗДАВ’”.

Оператор вибору switch

Часто в програмуванні виникає задача вибору одного варіанта з багатьох. Можна це зробити за допомогою вкладених структур if/еlse. Однак зручніший спосіб - використання оператора вибору switch, синтаксис загального вигляду якого такий:

switch (switch_expression)

{ case constant1: statement1; [break;]

……………………

case constanti: statementi; [break;]

…………………......

case constantN: statementN; [break; ]

[default: statementN+1; ] }

Оператор switchвиконується так. Спочатку обчислюється значення виразу switch__expression. Тип значення повинен бути одним із цілих - char, int, unsigned int, long int і long unsigned. Обчислене значення зрівнюється зі значеннями констант вибору або константних виразів constant1, ... , constantN. Заборонено використовувати в якості константи вибору змінну. При співпадінні значення switch_expression із constanti виконується оператор statementi. Потім керування передається на оператор відразу після switch, якщо в i-й гілці є присутнім оператор break (оператор break здійснює негайний вихід з оператора switch). У протилежному випадку виконуються оператори в гілках i+1, i+2 і так далі доти, поки в них не зустрінеться оператор break або не буде виконаний оператор statement n+1.

Якщо значення switch_expression не збіглося з жодною з констант constanti,... , constantN, виконується оператор у гілці, позначеній default. При її відсутності виконується наступний після switch оператор.

Для прикладу напишемо програму, яка моделює роботу світлофора.

#include <iostream>

#include <conio.h>

void main()

{

using namespace std;

char ch;

cout<<"Enter letter:";

cin>>ch;

switch (ch) {

case 'r': cout<<"Stop! RED"<<endl; break;

case 'y': cout<<"Attention! YELLOW"<<endl; break;

case 'g': cout<<"Go! GREEN"<<endl; break;

default: cout<<"Wrong letter!"<<endl;

}

_getch();

}

Оператор безумовного переходу

Для зміни послідовного виконання операторів використовується оператор безумовного переходу goto. Структура оператора goto:

goto <мітка>;

M

<мітка>: <оператор>;

Мітка задається за правилами запису ідентифікаторів. Якщо строго слідувати правилами структурного програмування, то нема ніякої необхідності в операторі безумовного переходу goto, який нещадно критикується в літературі по С++. Однак існують окремі випадки, коли його використання може принести певну користь. Ці випадки будуть розглядатися пізніше.

Наши рекомендации