Turbo Pascal. Programowanie

Turbo Pascal.
Programowanie

Autor: Tomasz M. Sadowski
Format: B5, stron: 136
Copyright © 1996 by Wydawnictwo Helion
wersja spakowana


Jak to się robi naprawdę?

Rozdział ten stanowi rozszerzenie poprzedniego i wcale nie musisz go czytać, chociaż może Ci się to przydać. Dowiesz się z niego, jak wyglądają poszczególne kroki procesu programowania i co oznaczają takie pojęcia jak algorytm, schemat blokowy czy projekt. Poznasz również kilka metod i wskazówek pozwalających na usystematyzowanie i uproszczenie pracy.

Problem

Programowanie nie istnieje samo dla siebie: aby w ogóle miało ono sens, musi służyć konkretnemu celowi. Przyczyną utworzenia programu musi być problem, który masz rozwiązać. Oczywiście, nie każdy problem da się rozwiązać w ten sposób, nie każdy też wymaga zastosowania komputera. Co więc kwalifikuje problem do zaprogramowania?

Problem przeznaczony do rozwiązania powinien być jasno zdefiniowany i wystarczająco złożony, by trud włożony w programowanie mógł się opłacić.

Metoda

Po ustaleniu co chcesz osiągnąć i jakimi informacjami dysponujesz, musisz ustalić sposób rozwiązania problemu. Niekiedy (jak w przypadku spadku swobodnego) sytuacja jest oczywista: należy zastosować wzór, który ktoś kiedyś wymyślił. Kiedy indziej trzeba wymyślić rozwiązanie samemu. Warto również zastanowić się nad przyjęciem założeń upraszczających, które mogą zmniejszyć nakład pracy potrzebny na stworzenie programu z niewielkim uszczerbkiem na dokładności.

Przykładem niech będzie wspomniana w poprzednim rozdziale kwestia wyznaczenia średniej długości zdania w tekście. Problem nie jest wcale wzięty "z sufitu": zarówno zbyt krótkie, jak i zbyt długie zdania zmniejszają czytelność tekstu, aby więc nie znudzić czytelnika, musisz trzymać się pewnego optimum, wynoszącego np. 60 znaków. Oto kilka konkurencyjnych rozwiązań tego problemu:

Najlepszą metodą na znalezienie metody jest sprawdzenie, czy ktoś jej już nie wymyślił. Po ustaleniu metody warto też zastanowić się nad jej uproszczeniem.

Algorytm

Skoro już mamy metodę, musimy zapisać ją w sposób formalny i szczegółowy. Po co? Komputer nie jest niestety na tyle inteligentny, by zrozumieć polecenie "zlicz wszystkie znaki w tekście"1, toteż musimy nasze zadanie przedstawić w sposób bardziej elementarny. Jak? Właśnie za pomocą algorytmu.

Zgodnie z definicją, algorytm to "zbiór określonych reguł postępowania, które realizowane zgodnie z ustalonym porządkiem umożliwiają rozwiązanie określonego zadania". Przekładając to na bardziej ludzki język możemy powiedzieć, że algorytm jest zapisem czynności, które należy krok po kroku wykonać w celu uzyskania wyniku. Zapisując algorytm musisz więc ustalić, jakie elementarne operacje będzie trzeba wykonać w trakcie realizacji zadania i jaka powinna być ich kolejność. Dodatkowo musisz określić tak zwane kryterium stopu, czyli warunek, którego spełnienie powoduje zakończenie wykonywania operacji (nie chcesz chyba czekać na wynik w nieskończoność).

Jak zapisać algorytm? Najprostszym sposobem jest słowne wyrażenie poszczególnych operacji w postaci punktów, np. tak:

  1. otwórz plik z tekstem do odczytu
  2. wyzeruj licznik znaków
  3. wyzeruj licznik kropek
  4. jeśli koniec pliku, to idź do punktu 9
  5. wczytaj kolejny znak z pliku
  6. jeśli znak jest kropką, zwiększ licznik kropek o 1
  7. zwiększ licznik znaków
  8. idź do punktu 4
  9. jeśli licznik kropek wynosi zero, idź do punktu 11
  10. wypisz (licznik znaków/(licznik kropek))
  11. STOP

To samo można przedstawić w postaci graficznej, zwanej schematem blokowym lub z angielska flowchart.

Rysunek 1. Schemat blokowy obliczania średniej liczby znaków w zdaniu

Schemat postępowania można wreszcie zapisać w postaci tak zwanego pseudokodu, czyli imitacji "prawdziwego" języka programowania:

  start
  otwórz(plik);
  znaki := 0;
  kropki := 0;
  dopóki nie koniec_pliku(plik)
    start
      czytaj (plik,znak) jeżeli znak = '.'
        kropki := kropki+1;
      znaki := znaki+1;
    stop;
  wypisz(znaki/kropki);
  stop.

Każda z powyższych metod ma swoje wady i zalety. Zapis poszczególnych kroków w postaci punktów jest prosty, ale przy bardziej złożonych zadaniach staje się mało czytelny. Zapis w postaci schematu blokowego jest bardzo czytelny, ale pracochłonny w wykonaniu. Wreszcie zapis w pseudokodzie ma tę zaletę, że po przetłumaczeniu na język angielski staje się praktycznie gotowym tekstem programu.

W myśl tego, co powiedzieliśmy na zakończenie poprzedniego punktu, nie musisz, a nawet nie powinieneś, wymyślać algorytmu samodzielnie. Jest to co prawda zajęcie bardzo kształcące i przynoszące dużo satysfakcji intelektualnej, jednak często okazuje się, że korzystając z gotowych rozwiązań można zrobić to samo znacznie efektywniej i szybciej. Niektóre problemy są natomiast na tyle nietypowe, iż metodę ich rozwiązania trzeba wymyślić od podstaw.

Omawiając algorytmy nie sposób pominąć kwestii struktur danych. Jest oczywiste, iż rozwiązanie jakiegokolwiek problemu wiąże się z przetwarzaniem informacji. Tę z kolei trzeba jakoś przechować, nie mówiąc już o wprowadzeniu jej do komputera i późniejszym wyprowadzeniu. Komputerowe sposoby reprezentowania informacji są znacznie ściślej określone, a jednocześnie znacznie mniej różnorodne niż te, których używamy na co dzień. W większości przypadków dobór odpowiedniej struktury danych jest automatyczny, gdyż albo narzuca się sam (np. rozwiązując zadanie matematyczne nie będziesz przedstawiał liczb w postaci znakowej), albo jest wymuszony przez algorytm. Czasem jednak sprawa nie jest tak oczywista. Przykładowo, konstruując program zajmujący się przetwarzaniem danych osobowych pracowników możesz zdecydować się na przechowywanie tychże danych w tak zwanych tablicach lub listach. Obydwa rozwiązania mają swoje zalety i wady, jak również wiążą się z zastosowaniem odpowiednich metod przetwarzania danych, czyli właśnie algorytmów.

Projekt

Jak już powiedzieliśmy, algorytm przeznaczony jest do rozwiązania zasadniczej części zadania i "nie przejmuje się" takimi detalami, jak wprowadzenie i wyprowadzenie danych czy utworzenie struktur danych. Na dodatek większość problemów jest na tyle skomplikowana, iż nie daje się rozwiązać za jednym zamachem. W takiej sytuacji musisz rozbić swoje zadanie na mniejsze fragmenty, dające się wyrazić za pomocą prostych algorytmów i uzupełnić ten zestaw przez opis operacji pomocniczych. Wszystko to należy powiązać w spójną całość, zwaną projektem programu.

Projekty mogą być tworzone dwiema przeciwstawnymi metodami, znanymi jako projektowanie wstępujące (ang. bottom-up design) oraz projektowanie zstępujące (ang. top-down design). Pierwsza z nich jest realizacją zasady "od szczegółu do ogółu": na samym początku określamy zestaw elementarnych zadań, których wykonanie będzie konieczne do realizacji głównego problemu (np. wprowadzanie danych, wyprowadzanie wyników, obliczanie wartości pośrednich). Po skonstruowaniu takich cegiełek budujemy z nich większe struktury, zajmujące się przetwarzaniem odpowiednio większych fragmentów zadania, z tych - struktury jeszcze bardziej ogólne, aż w końcu dochodzimy do głównego schematu działania, który zarządza poszczególnymi modułami.

Projektowanie zstępujące, jak nietrudno się domyślać, wygląda odwrotnie. Początkiem procesu jest ogólne sformułowanie zadania, które następnie poddaje się analizie i rozbiciu na współdziałające ze sobą części, te zaś dzieli się dalej aż do uzyskania elementarnych fragmentów, których zaprogramowanie jest już łatwe, a nawet typowe. Jednocześnie na każdym etapie podziału ulegają uściśleniu kompetencje poszczególnych fragmentów programu (a raczej projektu), czyli zakres przetwarzanych przezeń danych i postać zwracanych wyników.

Niezależnie od tego, jaką metodę zastosujesz, efektem projektowania powinno być uściślenie wybranej metody rozwiązania zadania i dostosowanie jej do konkretnych okoliczności i możliwości. Osiąga się to rozbijając zadanie na elementarne składniki, których rozwiązanie zostało już opisane lub jest łatwe do samodzielnego opracowania. Gotowy projekt może przyjąć postać podobną do omawianych przy okazji algorytmów: zapisu słownego lub graficznej reprezentacji ciągu czynności. Odpowiednie zapisanie poszczególnych elementów projektu znacznie ułatwi Ci jego implementację oraz przyszłe wprowadzanie zmian i ulepszeń.

Implementacja

Uff. Przynajmniej w teorii wszystko powinno już działać. Dysponując odpowiednio rozpisanym projektem można przystąpić do mechanicznej w zasadzie czynności programowania. Tak, to nie pomyłka: praktycznie całość pracy umysłowej poświęcanej na rozwiązanie danego zadania poprzez programowanie skupia się w etapach opisanych poprzednio. Samo programowanie (kodowanie) jest jedynie czynnością polegającą na przetłumaczeniu zapisu projektu na odpowiedni zapis symboliczny, czyli tak zwany język programowania (najczęściej wysokiego poziomu).

Zanim do tego dojdzie, możesz jeszcze stanąć przed koniecznością wyboru odpowiedniego języka, czyli narzędzia pracy (zakładając, że masz z czego wybierać, tj. potrafisz się posługiwać kilkoma językami).

Uruchomienie

Uruchamianie świeżo napisanych programów należy do bardziej ekscytujących momentów w życiu programisty. Pełny proces uruchamiania składa się z kilku etapów, które krótko opiszemy poniżej.

Napisany program należy po pierwsze przetłumaczyć na postać wykonywalną przez komputer, czyli (na ogół) skompilować go. Większość narzędzi programistycznych skutecznie wyłapie przy tej okazji wszelkie błędy literowe i składniowe, które miałeś okazję popełnić podczas wpisywania programu (błędy takie zwane są ogólnie błędami kompilacji).

Po wyeliminowaniu wszystkich błędów kompilacji możesz spróbować wykonać program. Przedtem jednak bezwzględnie zapisz go na dysku. W przypadku bardziej skomplikowanych programów efekty pierwszego uruchomienia mogą być dość zaskakujące, z zawieszeniem komputera włącznie: lepiej zapamiętać program, niż narażać się na konieczność odtwarzania części lub całości wyników pracy. Wszelkie błędy, które pojawiają się w trakcie pracy już uruchomionego programu, noszą nazwę błędów wykonania. Błędy te mogą powodować przerwanie działania programu (a nawet zawieszenielub restart komputera) lub jego zachowanie niezgodne z oczekiwaniami (np. brak reakcji na działania użytkownika, zwracanie błędnych wyników). Jeśli program po uruchomieniu zachowuje się w poprawnie (tj. nie zawiesił się, reaguje na próby komunikowania się z nim, zwraca w miarę poprawne wyniki i daje się zakończyć), możesz przejść do jego testowania.

Testowanie programu polega z grubsza na badaniu jego reakcji na różne zachowania użytkownika. Przede wszystkim należy sprawdzić, czy wynik pracy programu jest zgodny z naszymi oczekiwaniami. Jeśli tak, warto spróbować podrzucić mu do przetworzenia inne dane, dla których wynik znamy lub potrafimy obliczyć. Dobór danych do testowania nie powinien być przypadkowy, lecz winien opierać się na przewidywaniu możliwych słabych punktów programu. Przykładowo, jeśli program zajmuje się obsługą kartoteki pracowników, warto sprawdzić jego zachowanie w przypadku niepodania żadnego nazwiska, podania nazwiska dłuższego niż przyjęte maksimum itp. Dobrą metodą jest również testowanie programów przez użytkowników, którzy zwykle nie mają pojęcia o zasadach fair play obowiązujących w programowaniu i potrafią bardzo skutecznie "rozłożyć" programy uważane przez ich twórców za całkowicie bezbłędne. W przypadku uruchamiania bardzo opornych programów nieocenione usługi oddają wreszcie tzw. narzędzia uruchomieniowe, żargonowo zwane debuggerami. Pozwalają one na śledzenie i analizę zachowania programów instrukcja po instrukcji, co umożliwia lokalizację nawet bardzo wyrafinowanych błędów.

Zdrowy rozsądek

Jest on najważniejszym elementem procesu programowania (a dokładniej, jakiejkolwiek działalności praktycznej podejmowanej w życiu). Zastosowanie zdrowego rozsądku w programowaniu sprowadza się przede wszystkim do zachowania odpowiedniej proporcji pomiędzy treścią i formą oraz doboru metod odpowiednich do realizowanych zadań. Aby rozwiązać równanie kwadratowe możesz oczywiście napisać w Borland C++ 5.0 odpowiedni program dla Windows, wykonując uprzednio solidne przygotowanie w postaci schematu blokowego, listy zmiennych i spisu literatury. Możesz również nic nie pisać, a jedynie sięgnąć po kalkulator. W większości przypadków najlepsze jest rozwiązanie kompromisowe, tj. napisanie krótkiego programiku w Turbo Pascalu.

Samo przygotowanie teoretyczne również powinno być traktowane z umiarem. Dobór algorytmu czy opracowanie projektu bardzo często wykonywane są automatycznie, zaś ich rozpisywanie ma na celu jedynie ułatwienie ich zrozumienia i nie powinno być celem samym w sobie. Przeważająca część zadań, które będziesz rozwiązywał, jest na tyle prosta, iż nie wymaga specjalnych przygotowań. Powyższe uwagi powinieneś więc traktować raczej jako sposoby ułatwienia sobie rozwiązywania bardziej złożonych problemów, ewentualnie organizowania pracy zespołowej (o ile masz zamiar zostać zawodowym programistą).

Dysponując tymi wiadomościami możesz już spokojnie przejść do dzieła. W kolejnym rozdziale zapoznasz się z narzędziem, za pomocą którego będziesz tworzył programy.

Przypisy

1. Co prawda niektóre programy, jak np. Word dla Windows, udostępniają polecenie zliczania znaków w tekście, jednak jest ono właściwością programu, nie zaś komputera, i musiało zostać wcześniej zaprogramowane przez twórców edytora. | wróć |

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