4. Оператори за логическо управление на програмата. Логически оператор. Съставен оператор (оператор-блок). Оператор за безусловен преход. Оператор за избор.

Алгоритмите, чието програми писахме до сега, се наричат линейни. Те се състоят от наредени една след друга команди, които се изпълняват едни след други без никакви варианти от началото до края на алгоритъма. Чрез тези алгоритми могат да се решат обаче много тесен кръг прости задачи. Езикът Pascal притежава оператори, чрез които може да се наруши последователността на изпълняване на командите. Това се извършва според логиката на алгоритъма.

Логически оператор. Чрез този оператор програмата може по някакво логическо условие да се разклони в един или в два допълнителни клона. Той съществува в два варианта: непълен и пълен. Непълния оператор има следната граматика:

    if логически_израз
        then команда

Действието в този случай на оператора е следното: първо се изчислява логическия израз и ако той е истина (true), се изпълнява командата след ключовата дума then и се продължава нататък, ако изразът е лъжа (false), командата след then се прескача и се продължава нататък. Пример:

    if a < 0
         then a := -a

В резултат на този оператор, ако a е отрицателно число, то a приема стойността си с обратен знак, ако a е неотрицателно число, нищо не се прави - т. е. a получава абсолютната си стойност.

Пълният логически оператор има следната граматика:

    if логически_израз
        then команда1
         else команда2

Тук той има следното действие: първо се изчислява логическия израз и ако той е истина (true), се изпълнява команда1 след ключовата дума then и се продължава нататък, като се прескача команда2, ако изразът е лъжа (false), команда1 след then се прескача, а се изпълнява команда2 след ключовата дума else и се продължава нататък. Пример:

    if a < b
         then c := a
         else c := b

В резултат на този оператор, ако a е по-малко от b, тогава на c се присвоява а, иначе на c се присвоява b - т. е. на c се присвоява минималното от a и b.

Забележете, че след команда1 не се поставя ";". Напомняме, че ";" служи да раздели две поредни команди, а не е към командите. Ако поставите ";" след команда1, компилатора ще ви издаде съобщение за грешка "Error in statment" - "Грешка в оператора".

Съставен оператор. Често в програмата се налага според някакво логическо условие да се изпълни не една, а няколко команди. В оператора if обаче след then и след else може да има само по една команда. В този случай се използва съставния оператор, наречен още оператор - блок. Този оператор има следната граматика:

    begin
        команда 1;
        команда 2;
        .
        .
        команда N
    end

Той служи да групира няколко команди в една и може да бъде поставен на всяко едно място в програмата, където е допустима една отделна команда. Всъщност тялото на цялата програма е един съставен оператор. Всяка една команда вътре в съставния оператор може да е също съставен оператор или до съдържа в себе си съставни оператори. Така се получават много вложени един в друг съставни оператори, което позволява да се пишат произволно сложни програми с Pascal. Затова Pascal се определя като език с блокова структура. Пример:

    if a <= 0
        then begin
            write('Въведете ново число:');
            readln(a);
            b :=b + a
        end
    else b := b + a;

В този случай след then имаме съставен оператор групиращ в един оператор 3 команди. Забележете, че след end не се пише ";", защото следва else на оператора if.

Задача 4.1: Дадено е линейното уравнение

    a x + b = 0

Да се състави програма, която да решава това уравнение.

Анализ

Входни данни: a и b - реални.
Изход: Ако a и b са 0:         Всяко число;
            Ако a = 0, а b 0:   Няма решение;
            Иначе:                     x = -b / a

Алгоритъм

    Начало
        1. Въведи a, b
        2. Ако a = 0 и b = 0
            Изведи Всяко число
            Край
        3. Ако a = 0 и b 0
            Изведи Няма решение
            Край
        4. Ако a 0
            x <- -b / a
            Изведи x
    Край

Програма

program lneq;
    uses WinCrt;
    var
        a, b, x: real;
    begin
        write('Въведете двата коефициента:');
        readln(a, b);
         if (a = 0) and (b = 0)
   
         then writeln('Корен: Всяко число')
             else if a = 0
             then writeln('Корен: Няма')
            else begin
                x := -b / a;
                writeln('Корен:', x:8:4)
            end
    end.

Упътване: Във втория if не се проверява b 0, защото ако a = 0, b трябва да е различно от 0, иначе щеше условието на първия if да е true. След else на втория if трябва да се изпълнят две команди и затова се ползва съставен оператор.

Задача 4.2: Дадени са три отсечки. Да се състави програма, намираща лицето на триъгълника образуван от тях, ако те образуват триъгълник.

Анализ
    Входни данни: a > 0, b > 0, c > 0 - реални
    Изход:  Грешка: Отрицателна отсечка
                 Невъзможен триъгълник
                s - лицето по формулата на Херон

Алгоритъм

    Начало
        1. Въведи a, b, c
        2. Ако a <= 0 или b <= 0 или c <= 0
            Изведи Грешка: Отрицателна отсечка
            Край
        3. Ако a + b <= c или a + c <= c или b + c <= a
            Изведи Невъзможен триъгълник
            Край
        4. 
        5. 
        6. Изведи s
    Край

Програма

program lice;
    uses WinCrt;
    var
         a, b, c, p, s: real;
    begin
        write('Въведете дължините на три отсечки:');
        readln(a, b, c);
         if (a <= 0) or(b <= 0) or (c <= 0)
             then writeln('Грешка: Отрицателна отсечка')
             else if (a + b <= c) or (a + c <= b) or (b + c <= a)
             then writeln('Невъзможен триъгълник')
            else begin
                p := (a + b + c) / 2;
                s := sqrt(p * (p - a) * (p - b) * (p - c));
                writeln('Лице на триъгълника:', s:10:4)
            end
    end.

Оператор за безусловен преход. Този оператор служи да наруши последователното изпълнение на командите в програмата. Обикновено командите в програмата се изпълняват една след друга. Ако по някаква причина искаме да прескочим няколко команди или да се върнем назад с няколко команди, тогава може да се използва операторът за безусловен преход. Той е нехарактерен за стила на езика Pascal и е остатък от по-старите езици за програмиране. Доказано е, че всяка програма на Pascal може да се напише и без този оператор, като се използват други средства. Граматиката на оператора за безусловен преход е следната:

    goto етикет

където етикетът е цяло положително число. То се поставя пред командата от програмата, към която искаме да се извърши прехода:

    етикет: команда

Всички етикети в програмата трябва да са различни и да са описани в декларативната и част. Описанието е следното:

    label етикет1, етикет2, ... , етикетN;

Декларирането на етикетите става преди декларирането на константите и променливите (const и var) и след декларацията за ползвани библиотеки от готови подпрограми (uses). Пример:

program ...;
    uses .....
    label 1, 2; { Деклариране на етикетите }
    const .....
    var ....
    begin
1:     readln(a);
         if a > 0 then goto 2; { Преход напред }
        .....
         goto 1; { Преход назад - неявен цикъл }
        ...
2:     writeln(a);
        ....
    end.

В горната непълна програма два пъти се използва безусловен преход: напред - goto 2 и назад - goto 1. В първият случай се прескачат няколко команди, а във втория се връщаме назад няколко команди и те ще се изпълнят отново. Когато в един алгоритъм няколко команди се изпълняват многократно, се казва, че те образуват цикъл. Циклите образувани с оператора goto се наричат неявни цикли. В Pascal има специални оператори за цикъл.

Операторът goto е опасен за ползване, защото нарушава естествената логика на програмата. Чрез него тя се накъсва и става трудна за асимилиране. Това често води до грешки. Затова използването на goto би трябвало да се избягва. Съществуват обаче случаи, където опита да се избегне goto също усложнява и забавя програмата.

Задача 4.3: Да се състави програма, която събира N реални числа.

Анализ
    Входни данни: N>0 цяло
                              a1, a2, ... , aN - реални.
    Изход: s=a1+a2+...+aN

Алгоритъм

    Начало
        1. Въведи N
        2. Ако N <= 0
            Изведи Грешен брой
            Край
        3. s <- 0
        4. i <- 1
        5. Въведи ai
        6. s <- s+ai
        7. i <- i + 1
        8. Ако i <= N Отиди към 5
        9. Изведи s
    Край

Програма

program suma1;
    uses WinCrt;
    label 1, 2;
    var
        a, s: real;
        i, n: integer;
    begin
        write('Въведете броя на числата');
        readln(n);
         if n <= 0
            then begin
                writeln('Грешен брой!');
                 goto 2
            end;
        s := 0;
        i := 1;
1:     write('Въведете ', i, '-то число:');
        readln(a);
        s := s + a;
        i := i + 1;
         if i <= n then goto 1;
        writeln('Сума:', s:10:4);
2: end.

Коментар. В тази програма има два безусловни прехода. Първият (goto 2) е към края на програмата и вторият (goto 1) е няколко команди назад към началото. В този случай имаме неявен цикъл изхода, от който е с оператора if.

Оператор за избор. С помощта на логическия оператор if и съставен оператор можем според някакво условие да разклоним алгоритъма на един или два клона. Често обаче се налага разклоняването на много клонове според някакви изброими ситуации (например избор от меню). Вместо да се правят каскади от вложени логически оператори, се използва оператор за избор. Той има следната граматика:

    case изброим_израз of
        константа1: команда1;
        констонта2: команда2;
        .
        .
        .
        константаN: командаN;
         else командаN+1
    end

else командаN+1 е незадължително. 

Дефиниция 4.1

Изброим израз е този, чието стойност може да се преброи. 

Такива са целите числа и символите. Реалните числа и низовете от символи не могат да се преброят. Действието на оператора case е следното: Първо се изчислява изброимия израз и неговата стойност се търси измежду изброените константи. Ако има константа съвпадаща със стойността на израза, то се изпълнява командата срещу тази константа. Ако стойността не съвпада с нито една от изброените константи, се изпълнява командата след else, ако има else, иначе, ако няма, нищо не се прави. Всяка една от командите вътре в оператора case може да е съставен оператор. Така се получават много разклонения в алгоритъма.

Пример 4.1:
case (k + 4) mod 6 of

    0: c := a + b;
    1, 3, 5: c := a - b;
    2: begin
            write('Въведете число:');
            readln(b);
            c := a + b
        end;
    else writeln('Грешка')
end;

От примера се вижда, че ако за няколко константи трябва да се изпълни една и съща команда, те се изброяват в списък.

Задача 4.4: Да се състави програма, която намира лицата на фигурите: окръжност по даден радиус, квадрат по дадена страна, правоъгълник по дадени две страни и триъгълник по дадени страна и височина към нея.

Анализ
    Входни данни: k = 1, 2, 3 или 4 - вид на фигурата, и съответните параметри на фигура, изброени в условието. Константа p = 3.1416.
    Изход: s - лице на съответната фигура.

Алгоритъм

    Начало
        1. Въведи k
        2. Ако k = 1
            Въведи r
            s <- p r2
        3. Ако k = 2
            Въведи a
            s <- a2
        4. Ако k = 3
            Въведи a, b
            s <- a b
        5. Ако k = 4
            Въведи a, h
            s <- a h / 2
        6. Иначе
            Изведи Грешен номер на фигура
            Отиди към 1
        7. Изведи s
    Край

Програма

program figurs;
    uses WinCrt;
    label 1;
    var
        a, b, h, r, s: real;
        k: integer;
    begin
1:     writeln('Вид фигура');
        writeln('1. Кръг');
        writeln('2. Квадрат');
        writeln('3. Правоъгълник');
        writeln('4. Триъгълник');
        write('Изберете:');
        readln(k);
         case k of
            1: begin
                     write('Въведете радиус:');
                     readln(r);
                    s := Pi * r * r;
                end;
            2: begin
                    writeln('Въведете страна:');
                    readln(a);
                    s := a * a;
                end;
            3: begin
                    writeln('Въведете две страни:');
                    readln(a, b);
                    s := a * b;
                end;
            4: begin
                    writeln('Въведете страна и височина към нея:');
                    readln(a, h);
                    s := a * h / 2;
                end;
            else begin
                writeln('Грешен номер на фигура !');
                 goto 1
            end
        end;
        writeln('Лице:', s:10:2);
    end.

Забележка: Pi е библиотечна константа за числото p . В програмата не се проверява дали дължините на отсечките са положителни числа.


Съдържание


3. Изрази: аритметични и логически изрази, видове операции и приоритет за тяхното изпълняване.


5. Оператори за цикъл. Оператори за цикъл с брояч, с предусловие и с постусловие.