Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

M_CI_4

.pdf
Скачиваний:
10
Добавлен:
12.05.2015
Размер:
821.43 Кб
Скачать

Лабораторна робота № 4.

(6 годин)

Оператори управління.

Мета роботи: здобуття знань та практичних навичок роботи з управляючими операторами мови Сі.

4. Теоретичнi вiдомостi.

Оператори управління призначені для зміни напрямку виконання програми, в залежності від виконання чи невиконання тих, чи інших умов, організації циклічного виконання групи операторів програми.

4.1. Оператор if.

Псевдокод оператора if:

if (логічний_вираз) if (логічний_вираз) оператор; {

оператор_1;

оператор_N;

}

а) б)

Оператор if працює так: якщо значенням логічного_виразу є "Істина", то виконується оператор (псевдокод а) або група операторів обмежена фігурними дужками (псевдокод б), які стоять після оператора і складають його тіло. В противному разі виконується оператор, який стоїть після тіла оператора if.

Надалі групу (два або більше) операторів, які об’єднані фігурними дужками будемо називати складеним оператором або блоком.

Примітка!

Порядок запису оператора не має значення для правильної компіляції, але має велике значення для зручності читання тексту програми.

Логічний_вираз може приймати різний вигляд, наприклад:

(арифметичний_вираз == значення) (арифметичний_вираз != 0) (арифметичний_вираз)

Між операторами

if (арифметичний_вираз != 0) оператор;

та

if (арифметичний_вираз) оператор;

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

Приклад: 4.1

 

 

 

 

 

 

1:

#include <stdio.h>

7:

scanf ("%d", &number);

2:

 

 

8:

okay = (1 <= number) && (number <=

3:

 

 

9:

10)

main()

if (!okay);

4:

{

 

10:

printf ("\n Відповідь неправильна!!! \n");

5:

int number, okay;

11:

return okay;

6:printf ("\n Введіть ціле число між 1 і 12: } 10\n");

42

Рядки 8 та 9 можна було б об`єднати. Тобто оператор if можна було б записати так: if (!(1 <= number) && (number <= 10));

Але, якщо критичною є ефективність виконання програми і потрібно повернути значення okay, то робити це не доцільно, оскільки значення логічного виразу потрібно буде вираховуватись два рази.

Зверніть увагу, що псевдокод оператора if має дві форми (а і б). Форма а) має тіло оператора if у вигляді одного оператора.

4.2. Оператор else.

Оператор else є розширенням оператора if. if (логічний_вираз)

оператор_1; else

оператор_2;

Оператори 1 та 2 можуть бути складними: if (логічний_вираз)

{

оператор_1;

оператор_N; } else {

оператор_N+1;

оператор_N+K;

}

Ці конструкції працюють так: якщо логічний_вираз має значення "Істина", то виконується оператор_1 або блок в який входять оператори з оператор_1 по оператор_N; в противному разі оператор_2 або блок в який входять оператори з оператор_N+1 по

оператор_N+K.

Можна вкладати кілька конструкцій if - else. if (логічний_вираз_1)

оператор_1;

else if (логічний_вираз_2) оператор_2;

else if (логічний_вираз_3) оператор_3;

else if (логічний_вираз_N) оператор_N;

else

оператор_N+1;

Ці конструкції працюють так: якщо логічний_вираз_1 має значення "Істина", то виконується оператор_1 і виконання програми продовжується з оператора, який стоїть після тіла останнього оператора else. В противному разі обчислюється і перевіряється значення логічного_виразу_2. Дія цієї частини конструкції така ж як і попередньої. Якщо ж ні один із логічних_виразів не має значення "Істина", то виконується тіло останнього оператора else.

Тіло останнього оператора else може бути пустим, або ж останній оператор else в цій конструкції може бути відсутній.

Приклад: 4.2

1:#include <stdio.h>

43

2:

3:main()

4:{

5: int leap_Year, year;

6:

7:printf("\n Введіть ціле число, яке позначає рік, наприклад, 1997:\n");

8:scanf("%d", &year);

9:if (year > 0)

10:

{

11:

if ((year % 100) == 0)

12:

leap_Year = ((year % 400) == 0);

13:

else

14:

leap_Year = ((year % 4) == 0);

15:

if(leap_Year != 0)

16:

printf("\n %d є високосним роком! \n", year);

17:

else

18:

printf("\n %d не високосний рік! \n", year);

19:

}

20:return 0;

21:}

Потрібно пам`ятати, що оператор else зв`язується з найближчим оператором if. Щоб впевнитись в цьому достатньо глянути на приклад 4.10 та результати роботи обох програм. А різниця між ними полягає в фігурних дужках в рядках 8 та 11.

Приклад: 4.3

 

 

 

 

 

 

 

 

1:

#include <stdio.h>

1:

#include <stdio.h>

2:

 

 

 

 

2:

 

 

3:

main()

 

 

3:

main()

4:

{

 

 

 

4:

{

 

5:

 

 

int value;

5:

 

int value;

6:

 

 

printf("\nВведіть ціле число між 1

6:

 

printf("\nВведіть ціле число між

7:

і

10\n");

7:

1

і 10\n");

 

 

scanf("%d", &value);

 

scanf("%d", &value);

8:

 

 

if (value >= 1)

8:

 

if (value >= 1)

9:

 

 

 

 

9:

 

{

 

 

if (value > 10)

 

if (value > 10)

10:

 

 

printf("\Значення більше

10:

 

printf("\Значення

11:

10!\n");

11:

 

більше 10!!!\n");

 

 

 

 

 

}

12:

 

 

else

12:

 

else

 

 

printf("\Значення менше 1!!!\n");

 

printf("\Значення менше 1!!!\n");

13:

 

 

return 0;

13:

 

return 0;

14: }

 

 

 

14:

}

 

 

 

 

Результат роботи

 

 

Результат роботи

Введiть цiле число мiж 1 и 10

Введiть цiле число мiж 1 и 10

5

 

 

 

 

5

 

 

Значення менше 1!

 

 

 

Введiть цiле число мiж 1 и 10

Введiть цiле число мiж 1 и 10

11

 

 

 

 

11

 

 

Значення бiльше 10!

Значення бiльше 10!

Введiть цiле число мiж 1 и 10

Введiть цiле число мiж 1 и 10

0

 

 

 

 

0

 

 

44

Значення менше 1!

4.3. Умовні вирази.

Конструкцію

if (вираз_1) вираз_2; else

вираз_3;

можна замінити на конструкцію, яка називається умовним виразом:

вираз_1 ? вираз_2 : вираз_3;

Спочатку обчислюється вираз_1. Якщо його значення істинне, то результатом всього виразу буде значення виразу_2, в противному разі - значення виразу_3.

Для чого потрібна така конструкція. Наприклад, розглянемо таку конструкцію: if (menu_choice == 'Y')

test_value = 100; else

test_value = 0;

Така конструкція потребує двох звертань до змінної test_value, а конструкція, що її замінює:

test_value = (menu_choice == 'Y') ? 100 : 0;

потребує всього одне звертання до змінної test_value.

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

4.4. Оператор switch.

Якщо потрібно зробити вибір із багатьох умов, замість конструкції if - else краще використати оператор switch:

switch (вираз)

{

case значення_1_виразу: оператор_1; break;

case значення_k_виразу: оператор_k; break;

case значення_N_виразу: оператор_N; break;

default:

оператор_замовчання;

}

Рядок

case значення_k_виразу:

порівнює константу значення_k_виразу з результатом обчислення виразу оператора switch. Якщо результат порівняння дасть значення "істина", то буде виконано оператор (або блок операторів), які слідують за рядком case. В противному разі, буде оброблятися наступний case–оператор. Якщо ж ні один із операторів case не дасть при порівнянні значення "істина", то буде виконано оператор_замовчання, яки слідує за оператором default. Оператор default є не-обов`язковим оператором.

45

Оператор break в кожному блоці case відразу виконує вихід із оператора switch. Якщо написати оператори switch без операторів break, то будуть виконані всі оператори_k в кожному операторі case.

Приклад:4.4

1:#include <stdio.h>

2:#include <ctype.h>

4:main()

5:{

6:int choice;

7:printf("\nМеню: Д (одати В (идалити С (ортувати З (акінчити: ");

8:choice = toupper (getchar());

9:switch (choice)

10:{

11:case 'Д' : printf("Ви вибрали Д (одати \n"); break;

12:case 'В' : printf("Ви вибрали В (идалити \n"); break;

13:case 'С' : printf("Ви вибрали С (ортувати \n"); break;

14:case 'З' : printf("Ви вибрали З (акінчити \n"); break;

15:default: printf("\nНеправильний вибiр!!! \n");

16:}

17:return choice;

18:}

4.5. Оператор while.

Цей оператор використовується для повторного виконання операторів на протязі всього часу, доки задана умова (вираз) є істинною. Псевдокод оператора має вигляд:

while (вираз)

{

оператор_1;

оператор_n

}

Приклад:4.5

 

 

 

 

 

1:

#include <stdio.h>

8:

while (counter <= 10)

2:

 

 

9:

{

3:

main()

10:

printf("%d\n", counter);

4:

{

 

11:

counter ++;

5:

int counter = 1;

12:

}

6:

printf(" Лічильник–while\n");

13:

return 0;

7:

 

 

14:

}

Цей приклад демонструє важливу властивість циклу while : якщо вираз, який аналізується буде з самого початку хибним, то тіло циклу не виконається ні разу.

4.6. Оператор do-while.

Оператор do-while у псевдокоді виглядить так:

do {

оператор

}while (вираз);

46

Виконується оператор, а потім перевіряється вираз. Доти, доки значення виразу буде істинним, оператор буде виконуватись.

Цикл do-while виконається хоча б один раз, навіть якщо значення виразу є хибним. Оператор do-while може бути простим або складним. Однооператорні цикли можна записати в одному рядку:

do оператор; while (вираз);

 

Приклад 4.6

 

 

 

 

 

 

 

 

 

# include <stdio.h>

1:

# include <stdio.h>

1:

2:

main()

2:

main()

3:

 

 

 

3:

 

4:

{

 

 

4:

{

5:

int counter;

5:

int letter;

6:

printf ("do-while – лічильник\n");

6:

printf ("do-while – абетка\n");

7:

counter = 0;

7:

letter = 'A' - 1;

8:

do {

8:

do {

9:

counter ++;

9:

letter ++;

10:

printf ("%d \n", counter);

10:

printf ("%c \n", letter);

11:

} while(counter < 10);

11:

} while(letter < 'Z');

12:

return 0;

12:

return 0;

13:

}

 

 

13:

}

4.7. Оператор for.

Коли точно відомо, або програма може підрахувати, скільки разів повинен виконатися блок операторів, то найкращим в цьому випадку є оператор циклу. Псевдокод оператора виглядає так:

for (вираз_1; вираз_2; вираз_3)

{

оператор

}

Цей оператор еквівалентний такому оператору while:

вираз_1; while(вираз_2;)

{

оператор вираз_3;

}

Вираз_1 в загальному випадку повинен ініціювати значення змінної циклу, вираз_2 повинен забезпечити закінчення циклу, а вираз_3 забезпечує зміну змінної циклу від

значення_виразу_1 до значення_виразу_2.

Наприклад цикли в попередніх прикладах можна було б замінити на такі:

for (counter = 0; counter < 10;

for (letter = 'A' - 1; letter < 'Z'

counter ++)

letter ++)

printf ("%d \n", counter);

printf ("%c \n", letter);

4.8. Оператор break.

При необхідності перервати цикли, які ми розглянули раніше, то необхідно використати оператор break.

Приклад 4.7

 

 

 

1:

# include <stdio.h>

if(counter > 5) break;

2:

main()

printf ("%d \n", counter);

47

3:

{

counter ++;

4:

int counter;

}

5:

printf ("\nfor - цикл\n");

printf ("\n do / while - цикл\n");

6:

for (counter = 1; counter <= 10; counter ++)

counter = 1;

7:

{

do {

8:

if(counter > 5) break;

if(counter > 5) break;

9:

printf ("%d \n", counter);

printf ("%d \n", counter);

10:

}

counter ++;

11:

printf ("\n while - цикл\n");

} while(counter <= 10);

12:

counter = 1;

return 0;

13:

while(counter <= 10);

}

Вцьому прикладі використовується конструкція for ( ; ; ) ;

{

if(вираз) break;

}

Тіло оператора буде виконуватись до тих пір, коли значення виразу не стане дорівнювати "істині".

4.9. Оператор continue.

Оператор continue схожий за дією з оператором break, але він примушує цикл перервати поточну ітерацію і почати наступну.

Приклад 4.8

1:# include <stdio.h>

2:main()

3:{

4:int counter;

5:printf ("\nПочаток for - циклу з continue \n");

6:for (counter = 1; counter <= 10; counter ++)

7:{

8:if(counter > 5) continue;

9:printf ("Після циклу for значення counter = %d \n", counter);

10:}

11:printf ("\nПочаток for - циклу з break \n");

12:for (counter = 1; counter <= 10; counter ++)

13:{

14:if(counter > 5) break;

15:printf ("Після циклу for значення counter = %d \n", counter);

16:}

17:return 0;

18:}

4.10. Оператор goto.

Оператор goto виконує перехід з того місця, де він зустрічається, на оператор, перед яким стоїть мітка.

Псевдокод оператора такий:

goto ім`я_мітки;

або

 

ім`я_мітки:

ім`я_мітки:

 

оператор;

48

 

оператор;

 

...

 

 

 

 

 

goto ім`я_мітки;

 

 

ім`я_мітки може бути таким як будь-який ідентифікатор в мові Сі. Але його прийнято

писати великими буквами.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Зверніть увагу!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Після імені_мітки, перед тим оператором, на який повинен виконатись перехід,

повинен стояти символ "двокрапка".

 

 

 

 

 

 

 

 

 

 

 

 

 

Приклад:4.9

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1:

 

main()

6:

printf ("%d \n", counter);

 

2:

{

 

 

7:

counter ++;

3:

 

int counter = 1;

8:

if(counter <=10) goto TOP;

4:

 

 

 

 

9:

return 0;

5:

 

TOP:

10:

}

 

 

 

В даному прикладі, коли умова counter <=10 в операторі if є істинною, то виконується

перехід на оператор, перед яким стоїть мітка TOP.

Сам по собі оператор goto не використовується, а тільки в тілі оператора вибору.

4.11. Функція exit().

Функція main() повинна закінчуватись оператором return value; який повертає операційній системі або програмі, яка запускає дану програму на виконання, якесь значення (value) після закінчення функції main().

Іншим способом закінчення програми є використання функції exit(), синтаксис якої має такий вигляд:

void exit(int status);

Прототип функції визначено у файлах process.h і stdlib.h.

Виконання оператора призводить до "виштовхування" інформації із буферів, закриття відкритих файлів та завершення програми.

Приклад 4.10:

 

 

 

 

1:

#include <stdlib.h>

9:

printf("Enter either 1 or 2\n");

2:

#include <conio.h>

10:

status = getch();

3:

#include <stdio.h>

11:

/* Sets DOS errorlevel */

4:

 

12:

exit(status - '0');

5:

int main(void)

13:

 

6:

{

14:

/* Note: this line is never reached */

7:

int status;

15:

return 0;

8:

 

16:

}

4.12. Алгоритми.

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

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

Ми розглянемо найбільш прості форми запису алгоритмів. При цьому ми будемо намагатись, щоб запис будь-якого алгоритму була зрозумілим кожному виконавцю, і кожен виконавець оформляв алгоритм однаково, тобто для одних і тих же вихідних даних в процесі його роботи виходили однаковими як всі проміжні, так і кінцеві результати.

Розглянемо кілька прикладів алгоритмів у двох формах запису – словесно–формульній та у вигляді блок схеми.

49

0i n1

Приклад 4.11.

Хай дані числа Х1, Х2, Х3. Найти найбільше серед них. Для вирішення цієї задачі ми зробимо так: візьмемо порівняємо перші два числа і запам’ятаємо значення більшого із них в додатковій змінній U. Потім порівняємо значення U зі значенням Х3. Більше значення знову ж таки запам’ятаємо в змінній U. В результаті ми одержимо значення U, яке є найбільшим із

чисел Х1, Х2, Х3.

Запишемо даний алгоритм більш чітко так:

1.Якщо Х1 ≥ Х2, то U = Х1, інакше U = Х2;

2.Якщо U ≤ Х3, то U = Х3, інакше перейти на пункт 3;

3.Стоп.

В даному записі дія запам’ятовування значення позначається знаком операції присвоєння.

Приклад 4.12.

Задана послідовність n чисел a1, a2, …, an (n ≥ 2), потрібно знайти найбільше із них, тобто

U = max {ai}

1i n

Алгоритм вирішення цієї задачі буде подібним до попереднього, але додатково буде використовуватись цикл, для перебору всієї послідовності. Перш за все ми повинні перенумерувати члени послідовності таким чином: a0, a1, …, an-1 (n ≥ 2); при цьому умова задачі буде виглядати так:

U = max {ai}.

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

Алгоритм у словесно-формульній формі буде виглядати так:

1.i = 0;

2.U = a0;

3.Якщо i < n, то перейти до пункту 4, інакше перейти до пункту 8;

4.Якщо U ≥ ai, то перейти до пункту 6;

5.U = ai

6.i = i + 1;

7.Перейти до пункту 3;

8.Стоп.

В цьому алгоритмі пп. 1, 2 та 8 виконуються по одному разу, а пп. 3-7 утворюють цикл, який виконується n раз (вони тут і надалі виділяються квадратною дужкою).

Приклад 4.13.

Потрібно вирахувати значення багаточлена Pn (x) ступеню n в деякій точці x.

Багаточлен можна представити традиційною формою

Pn (x) = an xn + an1xn1 +... + a1x + a0 ,

а можна у відповідності зі схемою Горнера:

Pn (x) = (...((an x +an1)x + an2 )x +...a1)x +a0.

Наприклад, для n=4

Pn (x) = (((a4x +a3)x +a2 )x +a1)x +a0.

Алгоритм обчислення багаточлена по схемі Горнера в словесно-формульній формі може бути таким:

1. i = n;

50

2.S = 0;

3.S = S * x + ai;

4.i = i – 1;

5.Якщо i ≥ 0, то перейти до п. 3;

6.Стоп.

Даний алгоритм не залежить від степені багаточлена. Достатньо змінити значення n, збільшити кількість членів масиву a.

Приклад 4.14.

Найти корінь рівняння f (x) = 0, де f (x) - задана функція. Знайти точні корені

рівняння можна тільки в виключних випадках, звичайно коли є яка-небудь проста формула для коренів, які вона виражає через відомі величини. Наприклад, навіть для алгебраїчних рівнянь (тобто рівнянь, в яких f (x) - є алгебраїчним багаточленом степені n), корені можна

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

більше четвертої. Тому це рівняння в більшості випадків вирішують за допомогою

наближених методів. Один із них – метод ділення відрізка пополам.

 

Нехай f (x) - безперервна функція на відрізку [a, b] і відомо, що рівняння f (x) = 0

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

що знайти значення кореню

x0 з заданою точністю.

 

 

 

Щоб функція f (x) мала один корінь на відрізку [a, b],

потрібно, щоб вона мала на

кінцях цього відрізку значення різних знаків.

Можна покласти, що f (a) < 0

і f (b) > 0 .

Якщо ж в дійсності все навпаки f (a) > 0 і

f (b) < 0 , то можна точкиa і

b поміняти

ролями. Для цього потрібно виконати такі дії: l = a; a =b; b =l.

Тоді алгоритм обчислення знаходження кореня x0 в словесно-формульній формі може бути таким:

1.Якщо f (a) < 0, то перейти до п. 3;

2.l = a; a =b; b =l;

3.c = (a + b)/2.0;

4.Якщо f (c) =0 , то перейти до п. 10;

5.Якщо f (c) >0 , то перейти до п. 8;

6.a = c ;

7.Перейти до п. 9;

8.b = c ;

9.Якщо b a ε, то перейти до п. 3;

10.x0 =c ;

11.Стоп.

Іншим інструментом, який часто використовується для запису алгоритмів, є блок-схеми. Вони призначені для графічного зображення структури алгоритмів. Будь-яка блок-схема є послідовністю спеціальних графічних фігур, які визначають виконання заданих дій та зв'язків між ними. ГОСТ 19.002-80 встановлює правила виконання схем алгоритмів та програм. ГОСТ 19.003-80 встановлює умовні графічні позначення в схемах алгоритмів та програм, які відображають основні операції процесу обробки даних та програмування для систем програмного забезпечення обчислювальних машин, комплексів та систем. Перелік деяких із них, їх найменування, позначення та розміри обов’язкових символів та функції, які вони відображають, приведено в табл. 4.1.

51

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]