Смекни!
smekni.com

Мітки та переходи (стр. 2 из 2)

Якщо замість набирання сталої натиснути на Ctrl-Z, то значення змінної v не читається, і вона зберігає своє старе значення. Якщо задати кінець послідовності відразу, то змінна v залишиться з невизначеним значенням. Тому радимо ініціалізувати змінні, значення яких читаються в циклі. Втім, варто ініціалізувати всі змінні, значення яких мають бути прочитані.

Відзначимо, що з повторних викликів функції eof, що виконуються вже після натискання на Ctrl-Z, буде повертатися значення true.

Приклад 3. Напишемо програму, за якою комп'ютер працює "майже як найпростіший калькулятор".

"Найпростіший калькулятор" працює так. Вхідні дані для нього утворюють послідовність вигляду

стала знак стала знак … стала,

де сталі задають дійсні числа, а знаки – операції +, -, *, /. Результат застосування чергової операції виводиться на екран і стає першим операндом наступної операції (якщо вона буде задана). Наприклад, результатом читання послідовності 1+2*4 буде 12, а не звичні 9 тому, що обчислюється 1+2=3 і потім 3*4=12.

Алгоритм роботи "найпростішого калькулятора" дуже простий:

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

Ми поки що не знаємо, як прочитати й подати символи "+", "-", "*", "/". Замість знаків "+", "-", "*", "/" будемо вживати цілі сталі 1, 2, 3, 4 відповідно. Нехай кожна стала набирається з нового рядка на клавіатурі й ознакою закінчення є натискання на Ctrl-Z замість уведення чергового знака операції.

Означимо змінні first і second для зберігання першого й другого операндів чергової операції. Позначення операції читається в змінну signop і після читання другого операнда застосовується операція. Результат операції записується на місце її першого операнда.

Найперше число не виводиться, тому що воно з'являється на екрані при набирании першої сталої. Одержуємо програму simplecalculator ("простий калькулятор"):

program simplecalculator (input, output);

var first, second : real;

signop : integer;

begin

writeln('Операції +, -, *, / позначаються числами 1, 2, 3, 4');

writeln('Задайте дійсне число : '); readln(first);

writeln('Задайте знак операції (1, 2, 3, 4) : ');

whilenot eof do

begin

readln(signop);

{Увага 1! }

writeln('Задайте дійсне число : '); readln(second);

if signop=1 then first:=first+second else

if signop=2 then first:=first-second else

if signop=3 then first:=first*second else

first:=first/second; {Увага 2! }

writeln('результат : ', first);

writeln('Задайте знак операції (1, 2, 3, 4) : ');

end

end.

Недоліком цієї програми є те, що в ній не вказано обробку можливих помилкових дій того, хто нею користується (користувача). Наприклад, якщо задати сталу 5, 6 тощо як знак операції, то буде виконуватися ділення. Навряд чи таке рішення має сенс. Крім того, якщо після знака ділення задати другий операнд 0, то при виконанні first/second відбувається ділення на 0, результат якого комп'ютеру "невідомий", і програма аварійно завершиться.

Доповнимо програму, щоб її осмислене виконання продовжувалося й після описаних помилок користувача. Такі доповнення називаються "захистом від дурня", а програма з ними – "дурнестійкою".

По-перше, якщо вказано недопустимий знак операції, повернемо користувача до задання нового знака операції, не примушуючи задавати другий операнд. Для цього скористаємося оператором continue (продовжувати виконання циклу з обчислення умови продовження).

По-друге, перед діленням варто перевірити, чи не рівний дільник нулю.

Така перевірка не завадить у будь-який програмі та в будь-якому її місці, де вказано ділення. У даному випадку ділення на 0 можна запобігти, також повернувши користувача до повторного задання знака операції і нового операнда (зрозуміло, можливі й інші рішення).

Отже, замість рядка з коментарем {Увага 1! } напишемо:

if (signop>4) or (signop<1) then

begin

writeln('-----Недопустимий знак операції-----');

writeln('Задайте знак операції (1, 2, 3, 4) : ');

continue

end;

Замість рядка з коментарем {Увага 2!}, що задає ділення, помістимо оператор:

if second<>0 then first:=first/second

else begin

writeln('-----Спроба ділення на 0: ігнорована-----');

writeln('Задайте знак операції (1, 2, 3, 4) : ');

continue

end;

Проте навіть із доповненнями програма "не захищена" від набирания символів, що не утворюють числову сталу. Для такого захисту потрібні засоби, які ми почнемо розглядати в розд. 14.-

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

Приклад 4. Відрізок [a; b] прямої задається координатами його кінців, тобто парою чисел a, b, де a£ b. Перетином двох відрізків є або відрізок, або порожня множина точок, наприклад, [1;3]Ç [2;4]=[2;3], [1;2]Ç [3;4]=Æ , [1;2]Ç [2;3]=[2;2].

Треба прочитати послідовність пар чисел, що задають відрізки, і знайти їх перетин.

Припустимо, кінець послідовності відрізків задається за допомогою "Ctrl-Z". Проте немає сенсу продовжувати читання відрізків після того, як перетин уже прочитаних став порожнім. У цьому випадку треба відразу видати відповідь і закінчити виконання програми. Припустимо, що можливо "неправильне" задання відрізків у вигляді пари чисел a, b, де a>b. У цьому випадку b і a міняються місцями.

Для збереження поточного перетину означимо змінні lb і hb (скорочення від "low bound" і "high bound" – нижня й верхня межа). Cпочатку відрізків немає, і перетин порожній – виразимо це ініціалізацією lb=1, hb=0, тобто відрізком з неможливими межами. Перший відрізок має стати значенням [lb;hb]. Потім у циклі вводяться інші відрізки та обчислюється перетин:

lb=1; hb=0;

writeln('задайте дійсні кінці відрізка:'); readln(a, b);

if a>b then

begin lb := b; hb := a end

else begin lb:=a; hb:=b end

{прочитано перший відрізок}

{далі читаються інші та обчислюється їх перетин}

whilenot eof do

begin

writeln('задайте дійсні кінці відрізка:'); readln(a, b);

if a>b then

begin t:=a; a:=b; b:=t end;

if a>lb then lb:=a;

if b<hb then hb:=b;

if lb>hb then break

end;

{введення закінчено або перетин порожній}

if lb>hb then

writeln('перетин порожній')

else writeln('перетин: [', lb, ';', hb, ']')

Оформлення програми залишаємо вправою.-