Цикли

Іноді в алгоритмі необхідно повернутися назад і знову виконати вже пройдену послідовність дій. Таке повторення зветься циклом. Так, у вигляді циклу можна записати, скажімо, алгоритм переміщень учня школи протягом тижня (дім - дорога - школа - дорога - дім - повторити). Найпростіше це можна реалізувати мітками, просто вказавши перехід на мітку, що знаходиться раніше команди goto; але, як ми вже казали, користуватися мітками не рекомендовано, тому в Паскалі є оператори циклів while-do, repeat-until та for-do.

Цикл while-do

Конструкція while умова do дія (англ. while - "доки", do - "виконати") або цикл з передумовою перевіряє умову, і якщо вона виконується, виконує дію, після чого знову перевіряє умову і т.д. Таким чином, фрагмент коду i:=1; while i<5 do begin writeln(i,'. Привіт!'); i:=i+1 end; виведе 4 пронумеровані рядки зі словом "Привіт!": 1. Привіт!

2. Привіт!

3. Привіт!

4. Привіт! П'ятий рядок не буде виведено, оскільки при i=5 не виконується умова i<5. Якби перед циклом значення 'i' було встановлено в 10, то команди всередині циклу (тіло циклу) не були б виконані взагалі жодного разу.

Цикл repeat-until

Конструкція repeat дії until умова(англ. repeat - "повторювати", until - "доки не") або цикл з післяумовою спершу виконує всі дії між repeat та until, після чого перевіряє умову. Якщо вона виконується, цикл завершується. Ось фрагмент програми, аналогічний попередньому: i:=1; repeat writeln(i,'. Привіт!'); i:=i+1 until i>=5;

Зверніть увагу на відмінності від циклу while-do: дій між repeat та until може бути декілька, тому нема потреби в операторних дужках begin-end; зверніть увагу на те, як зроблені відступи в цьому фрагменті коду; умова наприкінці є оберненою відносно умови в while-do, в першому випадку цикл продовжується, якщо умова істинна, в другому - завершується! якщо встановити заздалегідь істинне значення умови виходу, наприклад i:=10, то тіло циклу все одно буде виконано хоча б один раз.

Цикл for-do

Конструкція for змінна:=початок to кінець do дія(англ. for - "для", to - "до", do - "виконати") буде виконана рівно стільки разів, скільки треба, щоб змінити (додаючи по 1) значення змінної - лічильника від початкового значення до кінцевого. Так, попередня програма може бути записана в формі for i:=1 to 4 do writeln(i,'. Привіт!');

Основні відмінності циклу for-do від попередніх: дія після do одна, тому якщо треба виконати кілька дій в циклі, слід використовувати операторні дужки begin-end; кількість повторень циклу фіксована; більше того - кількість повторень обчислюється до початку циклу, і її неможливо змінити всередині циклу. Наприклад, s:=3; for i:=1 to s*s do begin s:=5; writeln(i) end; виведе числа від 1 до 9, хоча значення s при цьому зміниться! немає потреби у встановленні початкових значень до циклу, як і в "ручній" зміні параметра цикла - все буде виконано автоматично; якщо кінцеве значення менше за початкове, цикл не буде виконано жодного разу; лічильник (в прикладі i) має бути зліченого (цілого) типу і його не можна змінювати всередині циклу.

Загальні прийоми роботи із циклами

Треба бути обережним при написанні циклів: якщо всередині циклу не відбувається дій, які б змінювали істинність умови, цикл буде повторюватися нескінченно, доки програма не буде перервана системними засобами ("зависне"). Крім того, варто особливо уважно придивитися до першого і останнього проходу циклу, помилки частіше виникають в них. З огляду на це, якщо кількість проходжень циклу відома завчасно, слід використовувати цикл for-do: в ньому неможливе зациклювання, а перше і останнє значення лічильника одразу виписані.

Наприклад, якщо щось відбувається при значеннях змінної 2, 1, 0.5 і 0.25, то варто вручну перевірити, що відбудеться при значеннях 2 і 0.25, і чи дійсно в вашій програмі будуть такі значення, а не 4 і 0.125, бо зайвий прохід циклу - поширена помилка

Треба бути обережним при використанні циклу repeat-until: тіло циклу в ньому обов'язково буде хоча б один раз виконане, що при некоректних початкових умовах може бути небажаним. Завжди продумуйте в цьому циклі, що станеться, якщо умови некоректні; розгляньте можливість переробки програми в інший цикл.

Лічильником зветься змінна, що обраховує кількість повторень (і, відповідно, номер поточного повторення).

У всіх наведених вище циклах є лічильник; в циклі for-do лічильник є обов'язково, згідно з конструкцією цього циклу. Лічильник змінюється в кожному циклі за очевидним законом (зазвичай - на одиницю: i:=i+1). Для лічильників часто використовуються змінні з назвами i,j,k і т. д., хоча в цілому бажано давати змінним змістовніші імена.

Якщо умова зміни лічильника складніша, все одно іноді можна використовувати цикл for-do. Наприклад, щоб вивести на екран всі парні числа від 2 до 10, можна скористатися циклом while-do з додаванням 2 до лічильника: i:=2; while i<=10 do begin writeln(i); i:=i+2; end; а можна циклом for-do: for i:=1 to 5 do writeln(2*i);

Акумулятор - змінна, що "накопичує" в собі певне значення; вона є певним узагальненням лічильника. Ось програма, що обчислює кількість і суму введених чисел, доки не введуть 0:

program CountInput; var chyslo,lik,sum:integer; begin writeln('Вводьте числа по одному, для закінчення введіть 0'); lik:=0; sum:=0; chyslo:=0; repeat lik:=lik+1; sum:=sum+chyslo; readln(chyslo) until chyslo=0; writeln('Введено ', lik, ' чисел, сума = ', sum) end.

Зверніть увагу, що в цьому циклі є і акумулятор, і лічильник, але умова виходу із ними не пов'язана.

Акумулятор і лічильник перед циклом слід встановлювати в початкові значення ("занулювати"). В циклі for-do початкове значення лічильника встановлюється конструкцією циклу.

Переривання роботи циклу

Крім умови виходу і команди goto, є ще дві команди для переривання роботи циклу: continue і break. Перша припиняє виконання тіла і переходить на перевірку умови виходу з циклу; друга одразу переходить на наступну за циклом команду. Таким чином, цикл a:=0; while a<100 do begin a:=a+1; write(a,' '); if a<20 then continue; writeln('не менше 20'); if a=30 then break; end; буде виконано 30 разів, причому перші 19 буде виведено додаткове повідомлення. Одразу зауважте, що у випадку вкладених циклів ці оператори впливають тільки на внутрішній цикл. Як і у випадку з goto, використовувати ці команди небажано; але якщо є потреба, краще використовувати їх.

Структурне програмування

Спосіб написання програм без неочікуваних переходів (goto, break і continue), за допомогою трьох основних алгоритмів - лінійного виконання, розгалужень і циклів - зветься структурним програмуванням. Структурна програма зазвичай значно простіша для розуміння, що полегшує її розробку і підтримку. Для переробки неструктурованого циклу в структурований доводиться змінювати деякі умови і, іноді, вводити додаткові змінні, що містять ознаку певного стану - прапорці; зазвичай їх роблять типу boolean. Наприклад, код з попереднього підрозділу може бути записаний так: a:=0; while a<=30 do begin a:=a+1; write(a,' '); if a>=20 then writeln('не менше 20') end;

Завдання 1. Як переробити програму CountInput, щоб вона закінчувала роботу при перевищенні певної суми? 2. Написати програму, що виводить максимальний елемент серед введених чисел.