Turbo Pascal. Programowanie

Turbo Pascal.
Programowanie

Autor: Tomasz M. Sadowski
Format: B5, stron: 136

Copyright © 1996 by Wydawnictwo Helion
wersja spakowana

helion.pl

Instrukcja warunkowa

Aby uniknąć błędu wynikającego z próby pierwiastkowania liczby ujemnej, wypadałoby umieścić w naszym programie zastrzeżenie w postaci "jeżeli wyznacznik jest większy od zera to wykonaj dalsze obliczenia, w przeciwnym przypadku wypisz odpowiedni komunikat". Przekładając to na język angielski i nieco uogólniając, otrzymujemy strukturę instrukcji warunkowej:

if warunek
then instrukcja-1
else instrukcja-2

W powyższym zapisie warunek jest niczym innym, jak wyrażeniem dającym w wyniku wartość true lub false, na ogół wykorzystującym znane Ci już operatory relacyjne (mówiąc po ludzku, jest to zwykłe porównanie). Instrukcje opisują czynności, które powinny być wykonane po spełnieniu lub niespełnieniu warunku, przy czym część zaczynająca się od słowa kluczowego else nie jest obowiązkowa (tj. nie musisz określać "wariantu awaryjnego").

Instrukcja warunkowa, dostępna praktycznie w każdym języku programowania, stanowi podstawowe narzędzie umożliwiające podejmowanie decyzji w zależności od aktualnych warunków, czyli wbudowywanie w program "inteligencji", pozwalającej mu zachować się odpowiednio do sytuacji. Spróbujmy wkomponować instrukcję warunkową w nasz poprzedni program:

  program Nowe_Rownanie_Kwadratowe;
  { Program rozwiązuje równanie kwadratowe metodą wyznaczników }
  { uwzględniając możliwość ujemnego znaku wyznacznika }
   
  var
    a, b, c : real; { współczynniki }
    delta : real; { wyznacznik }
    x1, x2 : real; { pierwiastki }
   
  begin
    writeln('Program rozwiazuje rownanie kwadratowe')
    writeln('a*x^2 + b*x + c');
    write('Podaj wspolczynnik a: '); { wprowadź współczynniki }
    readln(a);
    write('Podaj wspolczynnik b: ');
    readln(b);
    write('Podaj wspolczynnik c: ');
    readln(c);
    delta := sqr(b) - 4*a*c; { oblicz wyznacznik }
    if delta >= 0 then { wyznacznik OK }
      begin { wykonujemy obliczenia }
        x1 := (-b + sqrt(delta))/(2*a); { oblicz pierwiastki }
        x2 := (-b - sqrt(delta))/(2*a);
        writeln('Pierwiastki:'); { wyświetl pierwiastki }
        writeln('x1 = ', x1:12:4); 
        writeln('x2 = ', x2:12:4);
      end { tu NIE MA średnika! }
    else { wyznacznik ujemny }
      writeln('Rownanie nie ma pierwiastkow rzeczywistych.');
    readln;
  end.

Postać warunku jest w naszym przypadku oczywista:

if delta >=0

czyli "jeżeli wyznacznik nie jest mniejszy od zera...". Zauważ, że jeśli warunek jest spełniony, należy wykonać więcej niż jedną instrukcję, a zatem cała grupa instrukcji zajmujących się obliczaniem i wyświetlaniem pierwiastków musi zostać otoczona słowami kluczowymi begin i end, oznaczającymi tzw. instrukcję złożoną, czyli zestaw instrukcji wykonywanych jako jedna całość. Zapominanie o tym wymaganiu jest jednym z pospolitszych błędów popełnianych przez programistów pascalowych (nie tylko początkujących) i może prowadzić do niezbyt przyjemnych błędów wykonania. Oto przykład:

  if n <> 0 then
    LiczbaProbek := n;
    srednia := suma/LiczbaProbek;

Powyższy fragment powinien przypisywać zmiennej LiczbaProbek wartość n, a następnie obliczać srednia jako suma podzielona przez LiczbaProbek, gwarantując, że w przypadku n równego zero dzielenie nie będzie wykonywane. Ponieważ jednak przypisania nie zostały połączone w instrukcję złożoną, dla n równego zeru pierwsze przypisanie nie wykona się, a zatem zmienna LiczbaProbek będzie miała wartość nieokreśloną. Może to być zero (wówczas wykonanie programu zostanie przerwane) lub dowolna wartość, co oczywiście doprowadzi do zupełnie bezsensownego wyniku. Prawidłowa postać powyższej instrukcji będzie wyglądała następująco:

  if n <> 0 then
    begin
      LiczbaProbek := n;
      srednia := suma/LiczbaProbek;
    end;

Wróćmy do naszego równania. Zauważ, że w pewnym szczególnym przypadku - gdy wyznacznik jest równy zeru - ma ono tylko jeden pierwiastek: jest tak dla równania

x2 + 2x + 1

którego podwójnym pierwiastkiem jest liczba -1. W tym przypadku musimy uwzględnić trzy możliwości, w zależności od wartości wyznacznika:

Wyznacznik
Pierwiastki
większy od zera

równy zeru
mniejszy od zera brak pierwiastków rzeczywistych

Ponieważ pojedyncza instrukcja warunkowa potrafi obsłużyć tylko dwie wzajemnie się wykluczające sytuacje, aby uwzględnić wszystkie warianty, niezbędne jest zagnieżdżenie dwóch takich instrukcji. Schemat postępowania pokazany jest poniżej; w ramach ćwiczeń proponuję Ci samodzielne dokonanie odpowiednich modyfikacji w programie.

  if delta < 0 then
    { brak pierwiastków rzeczywistych }
  else
    if delta = 0 then
      { oblicz i wypisz pojedynczy pierwiastek }
    else { odnosi się do drugiego if-a }
      { oblicz i wypisz obydwa pierwiastki }

W przypadku większej liczby wariantów takie "piętrowe" konstrukcje stają się nieporęczne, trudne w interpretacji i podatne na błędy. Zastanów się na przykład, jak wyglądałaby instrukcja warunkowa wypisująca na ekranie nazwę dnia tygodnia danego numerem (niech 1 oznacza poniedziałek). Może tak:

if dzien = 1 then writeln('Poniedzialek')
else if dzien = 2 then writeln('Wtorek')
else if ...

Co prawda używanie pełnej formy instrukcji warunkowej (if-then-else) nie jest tu konieczne i słowa else można usunąć (pamiętając o średnikach), jednak w dalszym ciągu powyższy twór będzie co najmniej nieelegancki. Skutecznym sposobem obsługi wyborów wielowariantowych jest instrukcja wyboru case, odpowiadająca z grubsza "stercie" zagnieżdżonych instrukcji warunkowych:

  case przełącznik of
    wartość-1 : akcja-1;
    wartość-2 : akcja-2;
    ...
    else akcja-domyślna
  end;

Powyższa struktura jest swoistą tablicą akcji odpowiadających poszczególnym wartościom zmiennej przełącznik i doskonale nadaje się do realizacji wielowariantowych wyborów, których klasycznym przykładem jest menu. Zauważ, że oprócz akcji skojarzonych z poszczególnymi wartościami przełącznika masz możliwość określenia akcji domyślnej, realizowanej w przypadku wystąpienia wartości nie znajdującej się w naszej "tablicy". Odpowiada za nią słowo kluczowe else umieszczone na końcu instrukcji. Pewnym ograniczeniem narzucanym przez instrukcję case jest wymaganie, by zmienna przełącznik była typu porządkowego (tak więc nie będziemy mogli zastosować jej w naszym programie, w którym wyznacznik jest liczbą rzeczywistą). Ułatwieniem natomiast jest możliwość "grupowego" definiowania wartości odpowiadających poszczególnym akcjom, np.:

  case liczba_interesantow of
    0 : mozna_wyjsc_do_fryzjera;
    1, 2 : niech_czekaja;
    3..6 : trzeba_obsluzyc;
    else wypisz('INWENTARYZACJA')
  end;

Wartości odpowiadające poszczególnym akcjom mogą być wyliczane jawnie lub podawane w postaci zakresów (od..do), o ile tylko tworzą ciągłą grupę. Musisz również pamiętać, że - w odróżnieniu od instrukcji warunkowej - przed słowem else możesz postawić średnik.

I to by było na tyle, co oczywiście nie znaczy, że możesz spocząć na laurach. Miło jest mieć program potrafiący rozwiązać równanie kwadratowe, jednak znacznie przyjemniejsze byłoby posiadanie narzędzia do rozwiązywania bardziej skomplikowanych równań. Ale czy to aby nie za trudne? Bynajmniej...

Zapamiętaj

Poprzedni | Spis treści | Następny | Wersja spakowana |