Podstawy TURBO PASCALA
Nie będę tutaj lał wody, więc od razu zacznijmy od konkretów!
Pascal jest doskonałym narzędziem do robienia programów. Polega to na tym, że najpierw piszemy kod programu, a potem, żeby go przerobić na plik wykonywalny (z końcówką EXE) musimy go skompilować. Wszystkie te czynności wykonujemy za pomocą programu TURBO PASCAL. Po włączeniu widzimy najczęściej niebieski ekran. Z polecenia FILE i SAVE, zachowujemy pliki (tak jak w windowsie). Aby uruchomić napisany przez nas kod, używamy polecenia RUN i klikamy w pierwszą zakładkę (RUN). Aby go skompilować, klikamy w COMPILE i sprawdzamy, czy widnieje tam napis DESTINATION DISK. Jeżeli tak jest, klikamy na COMPILE. Jeżeli natomiast jest napis DESTINATION MEMORY, klikamy na ten napis i zmienia nam się MEMORY na DISK. Dalej wykonujemy jak wyżej.
Tak oto poznaliście podstawowe komendy w TP. Teraz zajmijmy się samym programem.
Podczas kompilacji wielokrotnie mogą wystąpić błędy. Jeżeli macie dobrą wersję TP/osobiście polecam 7.0/, to program pokaże wam jaki błąd zrobiliście i gdzie. Posiadacze starszych wersji muszą radzić sobie sami.
Jeżeli macie komputer powyżej Pentium (166 MHZ) to macie dużą szansę, że programy skompilowane na waszym Pascalu nie będą działać. Trzeba w tym celu ściągnąć sobie specjalnego patcha. Bez niego każdy program wykaże "RUN TIME ERROR"
Dalej
Polecenia BEGIN, END, WRITE, WRITELN
Główna część programu (tzw. blok główny) mieści się w dwóch wyrazach. Początek programu zaznaczamy pisząc BEGIN, koniec natomiast zaznaczamy słówkiem END. (koniecznie z kropką). Tak więc program, który nic nie robi, wygląda tak:
BEGIN
END.
Program się otwiera słówkiem BEGIN i kończy słówkiem END. Taki program jest oczywiście całkowicie bezużyteczny. W takim razie trzeba go trochę wzbogacić. Zacznijmy od polecenia WRITE. Rozkazuje ono napisanie jakiegoś tekstu. Przykład tekstu wygląda tak:
WRITE('Jakiś tekst niezbyt mądry');
Znasz już zatem polecenie WRITE. Na co należało by zwrócić uwagę? Między innymi na to, że tekst jak sami pewnie zauważyliście objęty jest w cudzysłowie (pojedyncze) i dodatkowo w nawiasy. Nawiasy zawsze będą istnieć przy poleceniu WRITE. Wszystko zostanie napisane co jest w nawiasie. W takim razie, po co jest cudzysłów? No więc, chodzi o to, że to co jest objęte w cudzysłowie zostanie na pewno wyświetlone na ekranie tak jak zostało to napisane. Dziwnie to brzmi, ale zobaczycie później. Komputer interpretuje to po prostu jako tekst i jeżeli chcemy coś zapisać, to zawsze w cudzysłów. I jeszcze jedno. Na końcu (za nawiasem) widnieje średnik. Zawsze trzeba go stosować na końcu polecenia. Inaczej program wskaże błędy. Potem się dowiesz, przy jakich poleceniach nie trzeba go stosować (między innymi przy poznanych już BEGIN i END). OK. A teraz mała sztuczka, która pokaże wam dwa istotne fakty. Spójrzcie na poniższy program:
BEGIN
write('wyraz numer 1');
write('wyraz numer 2');
write('wyraz numer 3);
END.
Widzimy tu program, który kolejno wypisze wyrazy. Po pierwsze - spróbujcie włączyć ten program. Na pewno zastanawiacie się, czemu nic się nie pokazało. To normalne. Komputer jest tak szybki, że zdążył pokazać te wyrazy i poleceniem END zamknął program. Zatem tak naprawdę, program zadziałał prawidłowo, ale my tego nie zauważyliśmy. Aby zobaczyć, co też komputer napisał musimy jakoś przerobić w/w kod, aby program zatrzymał się tuż przed jego końcem. Do tego służy polecenie READLN. Zastosowanie tego zostawmy sobie na później. Jak na razie będziemy stosować to tylko po to, abyśmy zobaczyli to co napisaliśmy. Tzn. zatrzymali program, aż do naciśnięcia jakiegoś klawisza. Zatem nasz program będzie wyglądał tak:
BEGIN
write('wyraz numer 1');
write('wyraz numer 2');
write('wyraz numer 3');
readln;
END.
I jak? Działa? Jak nie to coś pochrzaniłeś. Program powinien wyświetlić takie coś: "wyraz numer 1wyraz numer 2"...i tak dalej Zastanawiasz się pewnie dlaczego tak beznadziejnie to wygląda. Jest tak dlatego, że samo polecenie WRITE rozkazuje komputerowi napisać coś, a potem tak to zostawić. Następny zatem napis będzie zaraz po poprzednim, bez rozkazu zejścia niżej. W takim razie, powyższy program tak samo działa jak poniższy:
BEGIN
write('wyraz numer 1wyraz numer 2wyraz numer3');
readln;
END.
Porównajcie sobie dwa powyższe programy, a zobaczycie o co chodzi.
Teraz zajmijmy się czymś bardziej skomplikowanym. Załóżmy, że chcemy, aby program obliczył proste dodawanie. Spróbujcie zrobić eksperyment i napiszcie poniższy program:
BEGIN
write('2+3');
readln;
END.
I co się pokazało? Zamiast żądanego wyniku "5" na pewno napis "2+3", czyż nie? Zadziałało się tak dlatego, gdyż napisane było to w cudzysłowie. Komputer więc nie zwrócił uwagi, że jest to polecenie matematyczne. Po prostu napisał, to co mu kazałeś. Aby komputer wyświetlił napis "5" można albo po prostu napisać write('5'); lub coś takiego: write(2+3);. Czym się to różni? Tym, że nie ma tu cudzysłowu. Teraz już możecie śmiało wyliczać skomplikowane rzeczy.
A teraz nieco z innej parafii. Jak zrobić, aby tekst schodził akapit niżej? Nic trudniejszego. Wystarczy użyć polecenia WRITELN. Używa się go tak jak polecenia WRITE. Różni się tylko tym, że schodzi na końcu o jeden wers w dół. Poprawnie napisany program i przejrzyście wyglądający ma postać taką:
BEGIN
writeln;
writeln;
writeln;
write('2+3=');
write(2+3);
readln;
END.
Polecenie WRITELN; każe po prostu zejść linię niżej bez jakiegokolwiek tekstu. Następnie komputer napisze "2+3", po czym obliczy, że 2+3 jest 5 i napisze właśnie tą liczbę. Całość wyglądać będzie następująco: "2+3=5". Czyż PASCAL nie jest wspaniały?
Kolejna sprawa to, oddzielenia. Do w/w polecenia, gdzie komputer ma wyliczyć, ile jest 2+3, nie musimy używać aż dwóch poleceń WRITE. Wystarczy jedno polecenie, a teksty te należy oddzielić przecinkiem. Zatem poniższe trzy programy, działają tak samo. Przyjrzyjcie się im:
BEGIN
write('2+3=');
write(2+3);
readln;
END.
BEGIN
write('2+3=',2+3);
readln;
END.
BEGIN
write('2+3=5');
readln;
END.
Programy te wykonują to samo chociaż ich kod jest inny. Sposobów na wykonanie tak prostego działania jest wiele. Spróbuj sam wynaleźć inny sposób. Zwróćcie uwagę na środkowy program. Został tam użyty przecinek. Można go bez problemu używać. Spójrzcie jak wygląda program bez używania przecinku i po jego użyciu:
BEGIN
write(' tekst jakiś ');
write(9-2);
write(' drugi tekst ');
write('10');
readln;
END.
Był to prosty program , który wyświetli coś takiego: "tekst jakiś 7 drugi tekst 10". Spójrzcie na powyższy program i porównajcie go z programem poniżej:
BEGIN
write(' tekst jakiś ',9-2,' drugi tekst 10');
readln;
END.
Czyż nie jest prościej? Na tym właśnie polega stosowanie przecinka. I to byłby koniec tej lekcji. Zapraszam do następnej części.
Dalej
Polecenia READ, READLN, podstawy zmiennych
Na poprzedniej lekcji dowiedziałeś się, że program mieści się w znacznikach BEGIN i END. Dowiedziałeś się również, że TP można zmusić, aby coś napisał. Na tej lekcji postaramy się go zmusić, aby coś odczytał. Załóżmy, że chcemy, aby komputer wprowadził do pamięci jakieś imię. Chcemy zrobić program, który zapyta jak mamy na imię, po czym wyświetli nam napis: "Cześć (i tu imię). Miłego dnia!!!". Umiesz już napisać taki tekst, ale jak zrobić, żeby komputer wstawił do tekstu imię. Ponadto najpierw trzeba o to imię zapytać, a dopiero potem wstawić. Do tego służą tzw. zmienne. Zmienne możemy oznaczać dowolną literą lub wyrazem. Załóżmy, że zmienną, która będzie reprezentować imię użytkownika, nazwiemy po prostu "imie" (bez polskich liter). W TURBO PASCALU każdą zmienną musimy najpierw zdeklarować zanim jej użyjemy. Zmienne deklarujemy poleceniem "VAR" i robimy to jeszcze przed programem (przed poleceniem BEGIN). Po słowie "VAR" wypisujemy wszystkie zmienne. W naszym programie będzie tylko jedna zmienna o nazwie "imie". Po jej napisaniu trzeba jeszcze przypisać jej typ. Na razie poznasz tylko podstawowe typy zmiennych. Jak każdy wie, imię człowieka składa się z liter, więc jest to zwykły ciąg liter. Zmienna nasza będzie zatem typu STRING. Zapamiętajcie tę nazwę. Program, który zadeklaruje zmienną będzie więc wyglądał tak:
VAR
imie:string;
BEGIN
END.
Mamy więc program, który deklaruje zmienną typu STRING (czyli ciąg znaków). Teraz (w głównym bloku programu między BEGIN i END) musimy coś napisać, aby komputer spytał użytkownika jak ma na imię. Nic prostszego:
VAR
imie:string;
BEGIN
write('Jak masz na imię?');
END.
Już jesteśmy o krok dalej. Teraz musimy jakoś zatrzymać program, aby gość siedzący przed komputerem mógł napisać jak ma na imię i nacisnąć ENTER. Nic prostego. Do tego służy polecenie READ. Więc wstawmy to polecenia do naszego programu:
VAR
imie:string;
BEGIN
write('Jak masz na imię?');
read(imie);
END.
Zwróćcie uwagę na konstrukcję READ. W nawiasie podajemy zmienną, do której ma być zapisana wartość z klawiatury. To znaczy, że to, co użytkownik napisze będzie liczone jako zmienna "imie". Do polecenia w nawiasie nie stosujemy cudzysłowu i pamiętamy, żeby na końcu postawić średnik. Kolejnym krokiem będzie wykombinowanie, aby program napisał ładne powitanie z imieniem. Robimy to następująco:
VAR
imie:string;
BEGIN
write('Jak masz na imię?');
read(imie);
write('Witaj ');
write(imie);
write('. Życzę miłego dnia!!!');
readln;
END.
No to po kolei. Jak już zauważyłeś aby wyświetlić zmienną wystarczy użyć zwykłego polecenia WRITE podając w nawiasie nazwę zmiennej (bez cudzysłowu). Zwróć uwagę na linię "write('. Życzę miłego dnia!!!');" Kropka przed zdaniem jest po to, aby zdanie zakończyło się po imieniu. Jest to zabieg stylistyczny i nie służy do niczego specjalnego. Wszystko razem po włączeniu powinno wyglądać tak: "Witaj Zenek. Życzę miłego dnia!!!". Już wiesz po co ta kropka? Użytkownik nie wprowadzi jej przecież, a komputer nie zna naszego języka. Spróbuj bez kropki, a zobaczysz, co to znaczy estetyka programu. Ale jest to na szczęście niezbyt duży problem. A teraz jeszcze przeróbmy nasz kod programu, aby wyglądał on ładniej i miej miejsca zajmował. Tak, więc dobry kod programu wyglądałby tak:
VAR
imie:string;
BEGIN
writeln;
writeln('Jak masz na imię?');
writeln;
read(imie);
write('Witaj ',imie,'. Życzę miłego dnia!!!');
readln;
END.
W powyższym programie dodatkowo zostało dopisane zamiast WRITE, polecenie WRITELN, gdyż trzeba zauważyć, że nawet pytanie "Jak masz na imię?" musi ładnie wyglądać. Oprócz tego polecenia WRITELN; działają jak separator i nie pozwalają wszystkiego wyświetlić w jednej linii. Pokombinujcie z tymi poleceniami a zobaczycie, na czym to polega. Teraz spróbujmy wzbogacić nasz program. Załóżmy, że użytkownik wpisze jako swoje imię jakieś bzdety (na przykład 150 liter). Program zadziała, ale pomyślcie jak będzie to wyglądać. Trzeba, więc dać ograniczenie, aby użytkownik nie mógł wprowadzić zbyt wielu liter. Nie jest to specjalnie trudne. Wystarczy do typu zmiennej przypisać coś takiego:
VAR
imie:string[10];
BEGIN
writeln;
writeln('Jak masz na imię?');
writeln;
read(imie);
write('Witaj ',imie,'. Życzę miłego dnia!!!');
readln;
END.
Jak się pewnie już domyśliłeś, zmienna ta będzie ograniczona do dziesięciu liter. Użytkownik będzie mógł wprowadzić więcej liter, ale wyświetlone zostanie tylko dziesięć.
A teraz zajmijmy się liczbami. Zbudujmy prosty kalkulator, który będzie dodawał do siebie dwie liczby. Program najpierw spyta, jakie mają to być liczby, a potem je doda. Sama zasada jest podobna jak w przykładach powyżej, z tym, że zmienna będzie innego typu. Poza tym będziemy potrzebować nie jednej a dwóch zmiennych. Użytkownik przecież ma wprowadzić dwie liczby. Istnieją różne typy zmiennych oznaczające liczby. Dla początkujących użyjemy zmiennej typu LONGINT. Nie będę tłumaczył na czym ona polega, ale powiem, że mieści w sobie liczby od kilku miliardów albo nawet i więcej do minus kilku miliardów albo i nawet mniej :))) Powinna więc zadowolić każdego. Dodam jeszcze, że zapamiętuje tylko liczby całkowite, więc ułamki zostawmy sobie, na kiedy indziej. Zatem zacznijmy robić program. Poniżej znajduje się kod, który bez problemu powinieneś rozumieć:
VAR
liczba1:longint;
liczba2:longint;
BEGIN
writeln;
writeln('Podaj pierwszą liczbę');
read(liczba1);
writeln('Podaj drugą liczbę');
read(liczba2);
write('Ich suma wynosi: ',liczba1+liczba2);
readln;
END.
Zrozumiałe? Jeżeli nie to nie wiem coś ty za jeden. Oczywiście liczby można nie tylko dodawać, ale i dzielić, odejmować, mnożyć, podnosić do kwadratu itp. ale o tym w innej części kursu. Zaraz pod słówkiem "VAR" widzimy dwie zmienne: liczba1 i liczba2. Oba są typu LONGINT, czyli tego samego typu. Po co więc pisać dwa razy tą samą rzecz. Poprawiony program będzie więc wyglądał tak:
VAR
liczba1,liczba2:longint;
BEGIN
writeln;
writeln('Podaj pierwszą liczbę');
read(liczba1);
writeln('Podaj drugą liczbę');
read(liczba2);
write('Ich suma wynosi: ',liczba1+liczba2);
readln;
END.
Widzicie jakie to proste? Zatem zmienne tego samego typu można w ten właśnie sposób oddzielić przecinkami (bez spacji). Niby to nic takiego, ale wyobraźcie sobie, że mamy 50 takich zmiennych. Zamiast do wszystkich dopisywać typ, wystarczy wypisać je po przecinku.
Teraz poznamy jeszcze jedną sztuczkę. Załóżmy, że chcemy, aby jakaś zmienna miała już jakąś wartość. Na przykład do powyższego programu. Niech użytkownik nie wprowadza żadnej liczby, a program ma już zapisane w sobie ich wartości. Do tego służy instrukcja przypisania. Stosuje ją się bardzo prosto. Np. liczba1:=71; W ten sposób przypisaliśmy liczbę 71 do zmiennej "liczba1". Zwróćcie uwagę na znak przypisania. Jest to dwukropek i znak równości. Po tym wszystkim znajduje się oczywiście średnik. Zatem poniższy program nie zrobi nic innego, jak napisze liczbę 10:
VAR
liczba1,liczba2:longint;
BEGIN
liczba1:=2;
liczba2:=8;
write(liczba1+liczba2);
readln;
END.
Mam nadzieję, że wszyscy rozumieją, o co chodzi! Teraz nieco skomplikuję sprawę. Załóżmy, że chcemy, aby jedna zmienna była zależna od drugiej. Zróbmy pogram, który pyta użytkownika o jakąś liczbę i wyświetla ją pomnożoną przez 2. Można to zrobić w różny sposób. Spójrzcie na poniższy program. Jest to jeden ze sposobów.
VAR
liczba:longint;
BEGIN
writeln;
writeln('Podaj jakąś liczbę');
read(liczba);
write('Liczba ta pomnożona przez 2 wynosi ',liczba*2);
readln;
END.
Był to prosty sposób na pokazanie mnożenia (dokonujemy gwiazdką jakby co). Użytkownik wprowadził jakąś liczbę, a program ją wyświetlił, ale pomnożoną przez 2. A teraz spójrzcie na poniższy przykład. Działa on tak samo jak poprzedni, z tym, że jest inaczej zbudowany:
VAR
liczba,iloczyn:longint;
BEGIN
writeln;
writeln('Podaj jakąś liczbę');
read(liczba);
iloczyn:=liczba*2;
write('Liczba ta pomnożona przez 2 wynosi ',iloczyn);
readln;
END.
Był to nic innego jak przykład, że instrukcje przypisania można stosować nie tylko do liczb, ale i innych zmiennych, co daje nam już bardzo duże możliwości. Można przecież wykonać takie instrukcje przypisania jak: "liczba:=iloczyn*(iloczyn-1)-24" itp. O tym wszystkim dowiecie się później. Na razie najważniejsze jest, że wiecie, co to jest instrukcja przypisania i jak z niej korzystać. Teraz została jeszcze jedna sprawa. Jak przypisać do zmiennej typu STRING zwykły tekst. Nie jest to trudne. Wystarczy zastosować instrukcję przypisania, a samą wartość podać w cudzysłowie. Np: imie:='Franek'; Na koniec do omówienia zostało jeszcze polecenie READLN. Oprócz tego, że używamy READLN jak dotąd do przerywania programu, służy innym celom. Cele te jednak wykraczają jak na razie wasz zakres wiedzy, więc może innym razem. Zapraszam więc do następnej części
Podstawowe polecenia modułu CRT
Podstawowe polecenia modułu CRT
Wypadałoby tu zacząć od wyjaśnienia słowa "moduł". Otóż w Pascalu jest pełno poleceń, a wszystkie one nie są zasługą samego Pascala. Czasami do Pascala trzeba dorzucić jakiś moduł, aby one zadziałamy. Moduł CRT jest już w Pascalu wbudowany. Jest często stosowany w najróżniejszych programach i myślę, że ma użyteczne funkcję. Wszystkie moduły (nie tylko CRT) trzeba najpierw zdeklarować zanim się ich użyje, (czyli zanim użyje się ich poleceń). Zmienne deklarowaliśmy poleceniem "VAR", natomiast moduły deklarować będziemy za pomocą słówka "USES". Wpisujemy to jeszcze przed "VAR" na samym początku programu. Sam moduł tak właściwie niczym nie jest - daje tylko możliwość stosowania kilku nowych poleceń. Właśnie te kilka poleceń poznasz na tej lekcji. Zatem, najprostszy program, który ma moduł CRT, wygląda tak:
USES CRT;
BEGIN
END.
W ten właśnie sposób deklarujemy moduł CRT. Zwróć uwagę, że po słówku "USES" nie ma żadnego znaku. Na końcu linii pamiętamy oczywiście o średniku. Tak zdeklarowany moduł możemy wykorzystać. Najważniejsze z jego poleceń to:
1. CLRSCR;
To skomplikowane polecenie jest dość użyteczne. Po prostu czyści ekran z jakiegokolwiek tekstu. Każdy tekst znajdujący się po tym poleceniu będzie wyświetlany na czystym ekranie (żadnych innych rzeczy tam nie będzie jak dotychczas). Spróbuj napisać następujące programy i zobacz sam różnice:
USES CRT;
BEGIN
write('Jakiś tekst');
readln;
END.
USES CRT;
BEGIN
clrscr;
write('Jakiś tekst');
readln;
END.
Najpierw spróbuj włączyć pierwszy program, a potem drugi. Widzisz różnice?
2. DELAY(x);
Polecenie to daje możliwość wstrzymania programu na określoną ilość czasu (przydaje się zwłaszcza w programach demonstracyjnych). Za "x" wstawiamy czas, na jaki program ma być wstrzymany (1000 to jedna sekunda). Przykład programu z zastosowaniem polecenia DELAY znajduje się poniżej:
USES CRT;
BEGIN
write('Jakiś tekst numer 1');
delay(3500);
write('Jakiś tekst numer 2');
readln;
END.
Powyższy program napisze pierwsze zdanie i po upływie trzech i pół sekundy - drugie zdanie. Nie jest to chyba zbyt skomplikowane.
3. SOUND(x);
Przyszedł najwyższy czas, aby zademonstrować dźwięk. Nie będzie to dźwięk wydawany z głośników, a z tegoż urządzona, co się znajduje w środku komputera. Za "x" wstawiamy tzw. częstotliwość, tak samo jak w przypadku "DELAY". Samo polecenie "SOUND" nam nic nie da, gdyż komputer szybko odegra ten dźwięk i pojedzie dalej. Zaraz po poleceniu "SOUND" najlepiej stosować polecenie "DELAY", które zatrzyma dźwięk na określoną ilość czasu. W ten sposób możemy już grać proste melodyjki. Z osobistych doświadczeń wiem, że niektórzy nie wytrzymują dźwięku o częstotliwości 2200. Radzę popróbować. Ale najpierw przeczytajcie jeszcze poniższe polecenie.
4. NOSOUND;
Służy do przerywania jakiegokolwiek dźwięku wydobywającego się ze spikera. Na końcu programu radzę to stosować, bo może okazać się, że dźwięk nie ustanie. W celu przećwiczenia tych funkcji radzę napisać następujący program:
USES CRT;
BEGIN
sound(2200);
delay(5000);
nosound;
END.
Program ten przez pięć sekund da nam bardzo denerwujący dźwięk.
5. GOTOxy(współrzędne);
Załóżmy, że chcemy aby nasz tekst zaczynał się mniej więcej w środku ekranu. Stosowanie pięćdziesiąt razy polecenia "WRITELN;" a potem odmierzenie ilości spacji byłoby nieco niewygodne. Dlatego właśnie powstało polecenie "GOTOxy". Polecenie to rozkazuje przejście kursora do danej pozycji. Aby wszystko ładnie wyglądało, warto by było przedtem użyć "CLRSCR". Po poleceniu "GOTOxy" podajemy w nawiasach współrzędne. Pierwsza współrzędna jest odległością w poziomie (ilość kratek od lewej strony ekranu), druga zaś jest odległością w pionie (ilość kratek od górnej części ekranu). Możemy, więc napisać poniższy program.
USES CRT;
BEGIN
clrscr;
gotoxy(30,15);
write('Jakiś tekst');
readln;
END.
Powyższy tekst zaczynać się będzie w trzydziestej kolumnie i piętnastym wierszu. A teraz spróbujcie użyć ten sam program, ale bez polecenia "CLRSCR", a zobaczycie jak beznadziejnie będzie on wyglądał.
6. HALT;
W zasadzie, to polecenie "HALT" nie jest w składzie modułu CRT, i działa również bez niego, jednak chciałem go teraz opisać. Nie będzie to zbyt zawiłe, gdyż polecenie to robi nic innego, jak wychodzi z programu. Jak tylko program napotka to polecenie na swojej drodze, od razu przerywa program i natychmiast z niego wychodzi. Nie muszę chyba więcej wyjaśniać.
Jest oczywiście jeszcze wiele innych poleceń ze składni modułu CRT, ale staram się, aby wszystkie te polecenia były przyswajane powoli. Na razie powinieneś poćwiczyć z tym, co już umiesz. Dam ci małe zadanie domowe. Zrób program, który napisze najpierw kilka zdań, potem obliczy iloczyn dowolnych dwóch liczb wprowadzanych przez użytkownika, a na końcu wyświetli na środku ekranu napis "DOWIDZENIA!!!" przez pięć sekund. Niezłe zadanko, co? Ty już to umiesz!!!
Instrukcja warunkowa IF..THEN..ELSE oraz operatory
zanim zabrałeś się za bieżący. Wkraczamy, bowiem w coraz to bardziej trudne progi i niestety twoja koncentracja będzie musiała się bardziej wysilić. Ale dosyć już tego klepania, czas zaczynać. Załóżmy, że chcemy stworzyć program, który będzie pytał użytkownika o jakąś liczbę. Jest to oczywiście dla ciebie bułka z masłem, ale spróbujmy ten program rozbudować. Program Mam nadzieję, że ukończyłeś już lekturę wszystkich poprzednich części kursu ma pokazywać, czy liczba, którą wprowadził użytkownik jest większa od stu, mniejsza lub równa. Załóżmy, że użytkownik wprowadza liczbę 230. Program ma napisać, że liczba jest większa od stu. Jak użytkownik wprowadzi np. liczbę 17, to program ma napisać, że liczba jest mniejsza od stu. No i wreszcie, jak użytkownik wprowadzi 100, program napisze, że liczba, którą wprowadził użytkownik jest równa 100. Do tych zadań użyjemy jeszcze ci nieznanej instrukcji warunkowej. Zanim jednak się nią zajmiemy, napiszmy część programu, który może wyglądać tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
END.
Powyższy program nie powinien was dziwić - powinniście już go rozumieć. Teraz trzeba coś zrobić, aby program wykonał jedną z trzech opcji. Ma napisać, że liczba jest większa od stu albo mniejsza od stu albo równa. No to zaczynajmy. Zajmijmy się najpierw przypadkiem, gdzie liczba jest równa 100. Program będzie więc wyglądał tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba=100 THEN writeln('Podałeś liczbę równą 100');
readln;
END.
A teraz wyjaśnienie. Po słowie "IF" znajduje się zawsze warunek. W tym wypadku warunkiem jest przyrównanie liczby do stu. Jeżeli liczba jest równa 100, to program wykonuje to, co znajduje się po słowie "THEN". Jeżeli program stwierdzi, że nie jest to liczba 100, omija ten warunek całkowicie go ignorując. Rozumiecie? Teraz trzeba jeszcze przewidzieć dwa inne przypadki. Ktoś przecież może napisać liczbę mniejszą do sto albo większą. Cały program będzie więc wyglądał tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba=100 THEN writeln('Podałeś liczbę równą 100');
IF liczba>100 THEN writeln('Podałeś liczbę większą od 100');
IF liczba<100 THEN writeln('Podałeś liczbę mniejszą od 100');>
readln;
END.
W ten prosty sposób rozważyliśmy wszystkie możliwe przypadki. Logiczne jest że zawsze wystąpi jeden z tych trzech przypadków (bo każda liczba jest albo równa 100 albo mniejsza albo większa - innej możliwości nie ma). Logiczne także jest, że nie mogą się włączyć np. dwa warunki na raz. Przecież nie istnieje taka liczba, co by np. była jednocześnie większa od stu i mniejsza. Mam nadzieję, że to rozumiecie. Jak dotąd poznaliście trzy podstawowe operatory (równe, większe i mniejsze). Wszystkie podstawowe zebrane są poniżej:
= równe
> większe niż
< mniejsze niż
>= większe lub równe
<= mniejsze lub równe
<> różne
I wszystko jasne. A teraz kolej na następny "kwiatek" w TURBO PASCALU. Załóżmy, że chcemy zrobić instrukcję warunkową, co by sprawdzała, czy liczba, którą podał użytkownik równa jest 1000. Inne przypadki nas nie interesują, i gdy liczba nie jest równa tysiąc, następuje koniec programu. Można to zrobić metodą znaną, czyli tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba=1000 THEN writeln('Brawo! Podałeś liczbę tysiąc!');
IF liczba>1000 THEN halt;
IF liczba<1000 THEN halt;>
readln;
END.
Widzimy bardzo prosty program, który zaraz się kończy, gdy liczba, którą wprowadził użytkownik nie jest równa 1000. Są tam zastosowane dwie dodatkowe instrukcje,(gdy jest większa od 1000 lub mniejsza). Można to zrobić jeszcze inaczej:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba=1000 THEN writeln('Brawo! Podałeś liczbę tysiąc!');
IF liczba<>1000 THEN halt;
readln;
END.
Teraz program sprawdza, czy liczba jest różna od tysiąc a nie czy jest większa czy mniejsza. W sumie na jedno wychodzi, ale kod programu mniej zajmuje. Teraz poznasz trzeci sposób na wykonanie takiego programu. Służy do tego polecenie, "ELSE", który patrzy, czy użytkownik wprowadził inną liczbą niż przewidzianą. Spójrzcie na poniższy program:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba=1000 THEN writeln('Brawo! Podałeś liczbę tysiąc!')
ELSE halt;
readln;
END.
Polecenie ELSE zadziała, jeżeli użytkownik wprowadził liczbę, która nie była przewidziana przez wcześniejsze polecenie lub polecenia "IF". Zwróćcie uwagę na bardzo ważny szczegół. PRZED POLECENIEM ELSE NIE MA ŚREDNIKA. Jest to bardzo ważne i nawet dobrzy programiści o tym czasami zapominają. Zastosowanie "ELSE" lepiej ukazuje ten program:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę od 1 do 5');
read(liczba);
IF liczba=1 THEN writeln('Brawo! Podałeś liczbę 1');
IF liczba=2 THEN writeln('Brawo! Podałeś liczbę 2');
IF liczba=3 THEN writeln('Brawo! Podałeś liczbę 3')
ELSE writeln('Na pewno nie podałeś liczby 1, 2 lub 3');
readln;
END.
Przypominam jeszcze raz na brak średnika przed "ELSE" co doskonale ukazuje powyższy program. Teraz, gdy już znasz instrukcję warunkową, można przejść do bardziej skomplikowanych poleceń. Załóżmy, że program ma pytać użytkownika o dwie liczby. Najpierw program każe podać pierwszą liczbę. Potem program każe podać liczbę, która podzielona przez dwa daje liczbę pierwszą (czyli pierwsza liczba pomnożona przez dwa daje liczbę drugą). Będzie to takie zadanie dla użytkownika. Do tego musimy zastosować trochę bardziej skomplikowane obliczenia. Może tym razem od razu pokaże wam jak będzie wyglądał cały program (wierze w waszą inteligencję).
USES CRT;
VAR
liczba1,liczba2:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba1);
writeln('A teraz podaj ile to jest: pierwsza liczba pomnożona przez dwa?');
read(liczba2);
IF liczba1*2=liczba2 THEN writeln('Brawo! Umiesz mnożyć!!!');
IF liczba1*2<>liczba2 THEN writeln('Co ty? Mnożyć nie umiesz?');
readln;
END.
W programie tym zastosowaliśmy trochę matematyki. Program sprawdza, czy pierwsza liczba pomnożona przez dwa równa się liczbie drugiej. Jeżeli tak to program wypisuje odpowiedni tekst. Jeżeli nie to ochrzania użytkownika o nieumiejętność mnożenia. Niezłe co nie?
Przyszła kolej na następną ważną rzecz. Jak pewnie zauważyłeś, wszystkie poprzednie programy z instrukcją warunkową wykorzystywały tylko jedno polecenie po słówku "THEN". A co jeśli trzeba wykonać kilka rzeczy, jeżeli dany warunek zostanie spełniony. Niech na przykład użytkownik wprowadzi jakąś liczbę. Program ma się wyłączyć, jeżeli ta liczba jest większa od 50. Jeżeli liczba jest mniejsza, to program ma napisać coś i zagrać melodię. Widzimy, że program wykonać ma dwa polecenie. Nie można tego zrobić tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba>50 THEN halt;
IF liczba<=50 THEN writeln('Brawo! Liczba jest mniejsza lub równa 50');
sound(2200);
delay(3000);
readln;
END.
Jeżeli program ma grać, gdy liczba jest mniejsza lub równa 50, to powyższy program jest BŁĘDNY. Program nie wie, czy polecenie "SOUND" i następne należą do instrukcji warunkowej, czy są po prostu dalej. Prawidłowy program wyglądać będzie tak:
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba>50 THEN halt;
IF liczba<=50 THEN
BEGIN
writeln('Brawo! Liczba jest mniejsza lub równa 50');
sound(2200);
delay(3000);
END;
readln;
END.
W w/w programie, polecenia, które mają być wykonane gdy warunek zostanie spełniony są objęte w dodatkowe bloki, czyli między słówka "BEGIN" i "END;" (koniecznie END ze średnikiem). Przy bardziej skomplikowanych poleceniach trzeba uważać by się nie pogubić w tych wszystkich słówkach. Trzeba pamiętać, że każde "BEGIN" trzeba zamknąć "END". Zatem ilość słówek "BEGIN" jest równa ilości słówek "END". Widzicie, jakie to proste. Żeby jeszcze wam ułatwić sprawę, pokaże wam coś takiego jak wcięcia. Nie są to żadne polecenia, a sposób pisania programu, aby się w nim nie pogubić. Porównajcie powyższy program z poniższym.
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF liczba>50 THEN halt;
IF liczba<=50 THEN
BEGIN
writeln('Brawo! Liczba jest mniejsza lub równa 50');
sound(2200);
delay(3000);
END;
readln;
END.
Osobiście radzę stosować wcięcia, gdyż nie macie nawet pojęcia jak może to ułatwić tworzenie programu.
Kiedy już przebrnęliśmy przez podstawowe wieści, czas wreszcie zająć się "prawdziwymi" operatorami. Służą one do grupowania warunków. Załóżmy, że użytkownik ma wprowadzić liczbę od 1 do 10. Program ma pokazać, czy liczba, którą wprowadził użytkownik jest parzysta czy nie. Parzyste liczby z tego przedziału to 2, 4, 6, 8 i 10. Nieparzyste to: 1, 3, 5, 7, 9. Gdybyśmy liczyli na piechotę, program wyglądałby tak:
USES CRT;
VAR
liczba:longint
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę od 1 do 10');
read(liczba);
IF liczba=2 THEN writeln('Wprowdziłeś liczbę pażystą');
IF liczba=4 THEN writeln('Wprowdziłeś liczbę pażystą');
IF liczba=6 THEN writeln('Wprowdziłeś liczbę pażystą');
IF liczba=8 THEN writeln('Wprowdziłeś liczbę pażystą');
IF liczba=10 THEN writeln('Wprowdziłeś liczbę pażystą');
IF liczba=1 THEN writeln('Wprowdziłeś liczbę niepażystą');
IF liczba=3 THEN writeln('Wprowdziłeś liczbę niepażystą');
IF liczba=5 THEN writeln('Wprowdziłeś liczbę niepażystą');
IF liczba=7 THEN writeln('Wprowdziłeś liczbę niepażystą');
IF liczba=9 THEN writeln('Wprowdziłeś liczbę niepażystą');
readln;
END.
Trochę kosmicznie to wygląda, ale jest zrozumiałe. Program można by skrócić za pomocą operatorów. Pierwszym, jaki poznasz jest operator "OR" (alternatywa). Odpowiada polskiemu wyrazowi "lub". Doskonale nadaje się do tego programu. Spójrz na poniższy kod:
USES CRT;
VAR
liczba:longint
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę od 1 do 10');
read(liczba);
IF (liczba=2) OR (liczba=4) OR (liczba=6) OR (liczba=8) OR (liczba=10) THEN writeln('Wprowdziłeś liczbę pażystą');
IF (liczba=1) OR (liczba=3) OR (liczba=5) OR (liczba=7) OR (liczba=9) THEN writeln('Wprowdziłeś liczbę niepażystą');
readln;
END.
Program poprzedni miał taką formę:, "jeżeli liczba=2 to..., jeżeli liczba=4 to..., jeżeli liczba=6 to..." i tak dalej. Takiej formy się nie stosuje (jest poprawna, ale niewygodna). Program z operatorem ma taką postać:, "jeżeli liczba=2 lub liczba=4 lub liczb=6 lub liczba=8 lub liczba=10 to..." Chyba każdy widzi, że stosowanie operatorów jest łatwe. Pamiętać trzeba jeszcze, że jeżeli stosujemy jakikolwiek operator, to warunki muszą być w NAWIASACH. Doskonale to widać na powyższym programie. To był operator alternatywy ("OR"). Teraz czas poznać operator koniunkcji ("AND"). W powyższym programie napis się wyświetlał, gdy co najmniej jeden z warunków został spełniony. Gdybyśmy zastosowali tam "AND", każdy warunek musiałby być spełniony. Odpowiada to polskiemu wyrazowi "i". Wszystko się zaraz wyjaśni na podstawie programu. Załóżmy, że chcemy zrobić program, który sprawdza, czy liczba, którą wprowadził użytkownik jest między 5 a 10. Jeżeli tak, to ukaże się napis. Jeżeli nie - program się wyłączy. Zatem:
USES CRT;
VAR
liczba:longint
BEGIN
clrscr;
writeln('Wprowadź jakąś liczbę');
read(liczba);
IF (liczba>5) AND (liczba<10) THEN writeln('Liczba ta jest w przedziale od 5 do 10');>
IF (liczba>=10) OR (liczba<=5) THEN halt;
readln;
END.
Program ten wyłączy się, gdy liczba będzie większa lub równa 10 lub mniejsza/równa 5. Jeżeli jest mniejsza od dziesięciu i jednocześnie większa od 5, napis się ukaże. Poznałeś, zatem już 2 operatory (były one najważniejsze).
Zajmijmy się teraz operatorem "NOT". Jest to logiczne zaprzeczenie, czyli negacja. Nie jest on zbyt szeroko stosowany w programach, mimo to warto zwrócić na niego uwagę. Operator "NOT" po prostu neguje warunek. Pokaże wam to na przykładzie.
IF liczba<>10 THEN writeln('Liczba ta na pewno nie jest równa 10');
Powyższy program bada, czy liczba jest różna od 10. Jeżeli tak, to napis się ukaże. To samo można zrobić za pomocą operatora "NOT" w następujący sposób:
IF NOT liczba=10 THEN writeln('Liczba ta na pewno nie jest równa 10');
Czyli jeżeli liczba NIE równa się 10, to... itd. Mam nadzieję, że jest to zrozumiałe. Do opisania został jeszcze jeden operator, tzw. XOR, czyli alternatywa wykluczająca. Nie musicie się go uczyć, gdyż bardzo rzadko się go stosuje, ale jeśli ktoś czuje się na siłach, zaczynajmy. Operator XOR odpowiada wyrazowi "albo" (nie mylić z "lub"). Cała instrukcja zostaje spełniona, gdy jedno z dwóch warunków jest spełnione. Natomiast, gdy oba warunki są spełnione lub niespełnione - instrukcja się nie wykonuje (albo to albo to). To był właśnie operator XOR. Omówimy go jeszcze za moment. Teraz pokaże wam, jak można "sortować" operatory, tzn. nadawać im priorytety. Wystarczy użyć zwykłych nawiasów. Jeżeli chcemy wszystko objąć w jeszcze jeden nawias, śmiało go dajemy (zwykły, a nie żaden kwadratowy - taki, w jaki objęty jest ten tekst). Przykład zastosowania nawiasów znajduje się poniżej:
IF ((liczba1=10) AND (liczba2=20)) OR ((liczba1=5) AND (liczba2=15)) THEN "coś tam"...
W powyższym fragmencie instrukcja po słowie "THEN" zostanie spełnione w dwóch przypadkach.
Gdy liczba1=10 i liczba2=20
Gdy liczba1=5 i liczba2=15
Rozumiecie? Jak tak to dobrze.
To teraz jeszcze pokaże wam, jak działa XOR. Oba poniższe warunki znaczą to samo (tego rozumieć nie musicie, ale dobrze by było gdybyście chociaż zerknęli).
IF liczba1=10 XOR liczba2=20 THEN "coś tam"...
IF ((liczba1=10) AND (liczba2<>20)) OR ((liczba1<>10) AND (liczba2=20)) THEN "coś tam"...
To był właśnie przykład na "XOR" (wcale nie musieliście tego zrozumieć).
Dla podsumowania, przypomnijmy sobie wszystkie operatory.
OR - alternatywa - instrukcja się wykona, gdy co najmniej jeden z warunków jest spełniony ("lub").
AND - koniukcja - instrukcja się wykona, gdy wszystkie warunki są spełnione ("i").
NOT - negacja - zaprzeczenie warunku ("nie").
XOR - alternatywa wykluczająca - instrukcja się wykona tylko wtedy, gdy jeden z dwóch warunków jest spełniony ("albo").
W ten prosty sposób skończyliśmy piątą lekcję. Zapraszam do części szóstej.
Działania matematyczne
Moim zdaniem dysponujesz już sporą wiedzą, aby wkroczyć w następny poziom zaawansowania. Na poprzednich lekcjach poznałeś tylko znikomą część działań matematycznych, takich jak plus (+) czy minus (-). W tej lekcji postaram się objaśnić wam jak najwięcej takich działań. Stosuje się je tak jak inne. No to zaczynajmy.
+
Dodawanie. Np. 3+2=5, 8+10=18, 6+2=8.
-
Odejmowanie. Np. 3-2=1, 8-10=-2, 6-2=4.
*
Mnożenie. Np. 3*2=6, 8*10=80, 6*2=12.
/
Dzielenie. Np. 10/5=2, 6/2=3, 2/5=2,5.
To były podstawowe działania. Są jeszcze inne. Oto niektóre z nich:
div
Całkowita część z dzielenia. Np. 10 div 3=3, 6 div 4=1, 10 div 4=2.
mod
Reszta z dzielenia. Np. 5 mod 2=5, 10 mod 3=3333..., 1 mod 2=5.
sqrt
Pierwiastek. Np. sqrt(9)=3, sqrt(64)=8, sqrt(16)=4
sqr
Kwadrat (potęga druga). Np. sqr(2)=4, sqr(3)=9, sqr(10)=100.
abs
Wartość bezwzględna. Np. abs(3)=3, abs(-3)=3, abs(-230)=230.
Teorię mamy za sobą. Weźmy się za praktykę. Napiszmy program, który będzie podawał kwadrat, z liczby podanej przez użytkownika.
USES CRT;
VAR
liczba:longint;
BEGIN
clrscr;
writeln('Podaj jakąś liczbę');
read(liczba);
writeln('Kwadrat z liczby ',liczba,' wynosi ',sqr(liczba));
readln;
END.
Może wydawać ci się to trochę skomplikowane, ale po krótkiej analizie i kilku własnych programach, wszystko zrozumiesz. Teraz zróbmy program, który będzie pytał użytkownika o dwie liczby. Po podaniu liczb, program ma mówić, czy druga liczba jest dzielnikiem pierwszej. Np. gdy użytkownik poda liczby 10 i 2, program ma napisać, że 2 jest dzielnikiem 10. No to do roboty:
USES CRT;
VAR
liczba1,liczba2:longint;
BEGIN
clrscr;
writeln('Podaj pierwszą liczbę');
read(liczba1);
writeln('Podaj drugą liczbę');
read(liczba2);
IF liczba1 mod liczba2=0 THEN writeln(' Liczba ',liczba2,' jest dzielnikiem liczby ',liczba1);
IF liczba1 mod liczba2<>0 THEN writeln(' Liczba ',liczba2,' nie jest dzielnikiem liczby ',liczba1);
readln;
END.
Powyższy program sprawdza, czy reszta z dzielenia jednej liczby przez drugą jest równa zero czy też nie. Można to było zrobić jeszcze w inny sposób:
USES CRT;
VAR
liczba1,liczba2:longint;
BEGIN
clrscr;
writeln('Podaj pierwszą liczbę');
read(liczba1);
writeln('Podaj drugą liczbę');
read(liczba2);
IF liczba1 mod liczba2=0 THEN writeln(' Liczba ',liczba2,' jest dzielnikiem liczby ',liczba1)
ELSE writeln('Liczba ',liczba2,' nie jest dzielnikiem liczby ',liczba1);
readln;
END.
Zamiast całej instrukcji warunkowej użyłem polecenia "ELSE". Tego typu programy są bardzo ważne i musisz je znać. Radzę je dobrze poćwiczyć, zanim dojdziesz do następnej lekcji, gdyż będą one szeroko stosowane.
Praca domowa: zrób program, który pyta użytkownika o 3 liczby, a następnie sprawdza, czy liczba trzecia jest sumą dwóch pierwszych liczb. Jeżeli jest, to program ma wyświetlić dowolny komunikat i wydać jakiś dźwięk. Jeżeli nie jest - program ma się wyłączyć. POWODZENIA!
Pętle REPEAT..UNTIL oraz WHILE..DO
Nareszcie doszliśmy do tzw. pętli. Pętle są tak częste w programach, że nie sposób bez nich żyć. Jest ich kilka rodzajów. W tej części poznacie dwa z nich, bardzo zresztą podobne do siebie. Może zacznijmy od definicji, czym jest pętla w programie. Otóż przydaje się, gdy chcemy jakąś czynność (polecenie) wykonać określoną ilość razy. Nie będziemy oczywiście stosować metody "kopiuj / wklej" i tak np. 50 razy, gdyż jest to nieładne i czasochłonne i w ogóle tak się nie robi. Do tego są właśnie pętle. Zapętlają określony fragment kodu programu i rozkazują go wykonywać dopóki jakiś warunek zostanie spełniony. Pierwszy rodzaj pętli składa się z dwóch słów: "REPEAT" (powtarzaj) oraz "UNTIL" (dopóki). Zaraz powinno wam się wszystko w głowach rozjaśnić.
Załóżmy, że chcemy, aby program napisał coś takiego: "Witam cię po raz 1, witam cię po raz 2, witam cię po raz 3, witam cię po raz 4 ..." i tak dalej, aż do załóżmy 100. Nie będziemy przecież pisać 100 razy tej samej kwestii metodą kopiuj/wklej. Do tego użyjemy pętli. Wprowadźmy najpierw samą pętle, a potem wyjaśnijmy.
USES CRT;
BEGIN
clrscr;
REPEAT
(tu będą polecenia)
UNTIL (warunek)
readln;
END.
Wszystko, co będzie między znacznikami "REPEAT" i "UNTIL" będzie się w kółko powtarzało, aż warunek będzie spełniony. My chcemy, aby program wypisał 100 razy ten sam tekst z ciągle zwiększającą się liczbą o jeden. Zatem do dzieła:
USES CRT;
VAR
licznik:longint;
BEGIN
clrscr;
licznik:=0;
REPEAT
licznik:=licznik+1;
writeln('Witam cię po raz ',licznik);
UNTIL licznik=100
readln;
END.
A teraz wyjaśnienie. Na początku zdeklarowaliśmy zmienną o nazwie "licznik". Zaraz po "BEGIN" czyścimy ładnie ekran i zerujemy licznik (przypisujemy wartość 0). Zaczynamy pętle. Od tego momentu, zatem, wszystko będzie powtarzane. Licznik przyjmuje wartość "licznik+1". Licznik miał wartość 0, zatem 0+1 jest jeden. Licznik, więc ma wartość 1. Program rozkazuje napisać tekst i wstawić wartość licznika. Pętla się kończy. Program sprawdza, czy warunek jest spełniony. Aby pętla się zakończyła, wartość licznika musi wynosić 100. Nasz licznik aktualnie ma wartość 1. Zatem warunek nie został spełniony - program wraca do słowa "REPEAT". I znowu - licznik zwiększa swoją wartość o 1, czyli ma już 2. Rozkazuje napisać tekst i wstawić licznik. Sprawdza warunek - warunek nie jest spełniony - i znowu "REPEAT" Licznik podnosi swoją wartość do 3 i tak dalej. Pętla się zakończy, aż wartość licznika będzie równa 100. Gdy pętla się zakończy, program wykonuje dalsze instrukcje (w tym wypadku jest to "READLN"). I tak oto wyjaśniłem wam działanie pętli.
Jednakże jeden program to trochę mało, aby was czegoś nauczyć. Zróbmy teraz inny. Zróbmy program, który będzie kazał napisać użytkownikowi hasło. Hasło będzie cyfrowe, załóżmy, że liczba 123. Użytkownik nie będzie mógł wyjść z programu, aż napisze poprawne hasło. No to do dzieła:
USES CRT;
VAR
haslo:longint;
BEGIN
REPEAT
clrscr;
writeln('Podaj hasło!');
read(haslo);
UNTIL haslo=123;
writeln('BRAWO! Odgadłeś hasło!');
readln;
END.
Jak widzimy, pętla ta nie zakończy się, gdy ktoś poda nieprawidłowe hasło. I tak za każdym razem. Napis "Brawo..." wyświetli się tylko wtedy, gdy ktoś poda prawidłowe hasło.
Spróbujmy teraz zrobić program z innej parafii. Naszym celem jest napisanie prostego alarmu. Program ma wytwarzać dźwięk podobny do alarmu. Dodatkowo, tak napiszemy ten program, aby alarm zapiał 10 razy. Do dzieła:
USES CRT;
VAR
ilosc,ton:longint;
BEGIN
ilosc:=0;
ton:=0;
REPEAT
ton:=ton+1;
IF ton=1000 THEN
BEGIN
ton:=1;
ilosc:=ilosc+1;
END;
Sound(ton);
Delay(1);
UNTIL ilosc=10;
Nosound;
END.
Jak widzicie zdeklarowałem dwie zmienne: "ilosc" i "ton". Zmienna "ilosc" będzie nam mówiła ile razy alarm już zatrąbił. Zmienna "ton" decydować będzie to częstotliwości dźwięku. Najpierw zeruje oba zmienne. Później zaczynam pętle. Zmiennej "ton" zwiększam wartość (tak jak w poprzednich programach z pętlą). Program sprawdza, czy ta wartość równa jest sto. Na razie nie jest równa, więc program opuszcza instrukcję warunkową. Następnie przez 1/1000 sekundy wydobywa się dźwięk o częstotliwości "ton", czyli aktualnie 1. Pętla się zamyka. Następuje ponowne uruchomienie pętli, ponieważ wartość zmiennej "ilosc" nie jest równa 10. Kolejne zadania w pętli odgrywają dźwięk o coraz to wyższej częstotliwości. Daje to wrażenie alarmu. W pewnym momencie, zmienna "ton" jest już równa 1000, więc w pętli dokonuje się wstawiona tam instrukcja warunkowa. A w niej: "ton" przyjmuje wartość 1 oraz "ilosc" zwiększa swoją wartość o 1. Instrukcja warunkowa kończy się, a program odgrywa dźwięk o częstotliwości "ton", czyli znowu 1. I znowu wszystko zaczyna się, z tym, że wartość zmiennej "ilosc" jest większa. Cały proces trwa do momentu, aż zmienna "ilosc" przyjmie wartość 10. Program wtedy ucichnie dzięki poleceniu "NoSound". Skomplikowane, nieprawdaż? W praktyce usłyszysz 10 razy szybki wzrost częstotliwości. Da to efekt alarmu, zresztą - sam się przekonaj.
To teraz zajmijmy się poleceniem "WHILE..DO", które jest drugą pętlą omawianą na tej lekcji. Nie różni się zbytnio od poprzedniej, natomiast jest nieco rzadziej używana. W poprzedniej pętli, zawsze to, co było ujęte w nią - wykonało się, co najmniej raz. Musi tak być, ponieważ warunek na zakończenie pętli był na jej końcu. Program działał w sposób, że najpierw wykonał pętle, a potem dopiero sprawdził, czy to jej koniec. Pętla "WHILE..DO", najpierw sprawdza warunek, a potem dopiero, (jeżeli jest on spełniony) się wykonuje. Dlatego właśnie w tej pętli zaistnieć może sytuacja, że pętla w ogóle się nie włączy, gdy warunek nie będzie spełniony. Poza tym, program działa tak: dopóki warunek jest spełniony, wykonuj..., a nie jak poprzednio: wykonuj... aż warunek zostanie spełniony. Po słowie "WHILE" zawsze jest warunek. Potem następuje słowo "DO" i wpisujemy polecenia pętli. Po słowie "DO", musimy zastosować "BEGIN". Zatem wszystkie polecenia pętli muszą być ujęte w oddzielny blok. Wszystko zaraz się wyjaśni na konkretnym przykładzie (mam nadzieję).
Załóżmy, że chcemy zrobić prosty program, który pyta użytkownika o jakąś liczbę. Jeżeli ta liczba jest równa 10 lub 20, program wykonuje pętle. Jeżeli nie - program się wyłącza. Pętla polega na 10 krotnym wypisaniu słowa "Podałeś liczbę 10 lub 20". Program głupi jest i nieprzydatny, ale jak do ćwiczeń, to dobry. Starymi sposobami, program ten można zrobić tak:
USES CRT;
VAR
liczba,licznik:longint;
BEGIN
clrscr;
writeln('Podaj jakąś liczbę');
read(liczba);
IF (liczba=10) OR (liczba=20) THEN
BEGIN
licznik:=0;
REPEAT
licznik:=licznik+1;
writeln('Podałeś liczbę 10 lub 20');
UNTIL licznik=10;
writeln;
END;
Halt;
END.
Jak widzimy program ma dwie zmienne: "liczba" i "licznik". Użytkownik wprowadza liczbę. Jeżeli nie jest równa 10 lub 20, program opuszcza instrukcję warunkową, a zarazem pętle i dochodzi do polecenia "Halt". Jeżeli liczba równa jest 10 lub 20, program wykonuje instrukcję warunkową - wypisuje 10 razy napis. A teraz powyższy program przekształćmy, tak aby można było użyć w nim pętli "WHILE..DO". Będzie on wyglądał tak:
USES CRT;
VAR
liczba,licznik:longint;
BEGIN
clrscr;
writeln('Podaj jakąś liczbę');
read(liczba);
IF (liczba=10) OR (liczba=20) THEN
BEGIN
licznik:=0;
WHILE licznik<11 DO>
BEGIN
licznik:=licznik+1;
writeln('Podałeś liczbę 10 lub 20');
END;
writeln;
END;
Halt;
END.
Pętla sprawdza warunek, czy licznik<11. Jeżeli tak, pętla się wykonuje. Wykonuje się tak długo, aż licznik nie będzie mniejszy od 11 (czyli, aż osiągnie wartość 11). Z tego wynika, że napis wyświetli się 10 razy. Jak widzimy, łatwiej jest operować pętlą "REPEAT" niż omawianą. Ale jak to mówią: "róbta co chceta". Pamiętajcie, że w pętli "WHILE..DO" nie ma słowa "UNTIL".
Do omówienia zostało jeszcze zagnieżdżanie pętli. Czy wiesz, że w pętle można wpisać jeszcze jedną pętle, a w nią następną i następną... i tak dalej. My nie będziemy zapętlali miliony razy, ale zrobimy bardzo fajny program, który nazywać się będzie "tabliczka mnożenia". Jego zadaniem będzie wypisanie mnożeń, tzn. 1*1=1, 1*2=2, 1*3=3
aż dojdzie do 10*10=100. Wszystkie działania będą linijka pod linijką. Gdybyśmy chcieli to zrobić ręcznie, musielibyśmy zająć co najmniej 100 linijek tekstu (jedną na każde działanie), np:
writeln('4*3=12');
writeln('4*4=16');
writeln('4*5=20');
writeln('4*6=24');
writeln('4*7=28');
writeln('4*8=32');
writeln('4*9=36');
writeln('4*10=40');
writeln('5*1=5');
writeln('5*2=10');
writeln('5*3=15');
writeln('5*4=20');
i tak dalej...
Do tego celu zagnieździmy pętle. Tzn. wpiszemy drugą pętle "REPEAT" do już istniejącej. Najpierw zobaczcie na program, a potem sobie wyjaśnimy:
USES CRT;
VAR
a,b:longint;
BEGIN
clrscr;
writeln(' A oto tabliczka mnożenia:');
a:=0;
REPEAT
a:=a+1;
b:=0;
REPEAT
b:=b+1;
writeln(a,'*',b,'=',a*b);
delay(100);
UNTIL b=10;
UNTIL a=10;
END.
To teraz wyjaśnienie. Deklarujemy dwie zmienne: "a" i "b". Zmienna "a" będzie pierwszą liczbą, którą będziemy mnożyć, zmienna "b" natomiast - drugą. (a*b). Po napisie, zerujemy zmienną "a". Rozpoczynamy pętle ZEWNĘTRZNĄ. "a" zwiększa wartość o 1. Zerujemy "b". Zaczynamy pętle "WEWNĘTRZNĄ". "b" zwiększa wartość o 1. Program pisze: a*b=wynik. Zarówno "a" jak i "b" wynoszą 1, więc jest "1*1=1". Napis trwa 1/10 sekundy. Wartość "b" nie jest równa 10, więc pętla zaczyna się jeszcze raz. Znowu "b" zwiększa wartość, ale "a" pozostaje takie samo. Jest zatem 1*2=2. Jak zauważyliśmy, wszystko idzie dobrze. Tabliczka mnożenia idzie przez 1 do momentu, aż "b" wyniesie 10 (1*10=10). Pętla wewnętrzna się kończy. Pamiętamy jednak, że cały czas jesteśmy w pętli zewnętrznej. Pętla zewnętrzna kończy się dopiero, kiedy "a" jest równe 10. W tej chwili "a" jest równe 1, więc pętla zewnętrzna zaczyna się od początku. Wartość "b" się zeruje i zaczyna się pętla wewnętrzna. Teraz wszystko mnoży się przez "2". Zatem, w jednym poleceniu pętli zewnętrznej wykonuje się 10 razy pętla wewnętrzna. Pętla zewnętrzna wykonuje się 10 razy. Zatem końcowy napis będzie "10*10=100". Tak oto stworzyliśmy tabliczkę mnożenia dzięki podwójnej pętli (zagnieżdżeniu). Polecenie "Delay" służy tylko temu, abyśmy zdążyli tę tabliczkę zobaczyć, bo bez niego program ją wypisze w mgnieniu oka.
I to tyle, jeśli chodzi o te dwie pętle. Nie zaglądaj nawet do następnej lekcji, dopóki nie zrozumiesz tej - a zwłaszcza ostatniego programu z tabliczką mnożenia. Pamiętaj, że pętle są wykorzystywane w 90% programów, więc bez nich ani rusz.
Zadanie domowe: Napisz program, który pyta użytkownika o jakąś liczbę. Po wprowadzeniu liczby przez użytkownika, program ma pomnożyć ją przez wszystkie liczby od 1 do 2000 i pokazać wyniki (linijka pod linijką).
Pętle goto oraz FOR..TO..DO/FOR..DOWNTO..DO
W poprzednich pętlach tak naprawdę to nie wiadomo było ile razy się dana pętla wykona. Program mógł ciągnąć się w nieskończoność. Aby temu zapobiec, wymyślono pętle "FOR..TO..DO" oraz "FOR..DOWNTO..DO". Oba pętle nie różnią się zbyt od siebie. Zacznijmy może od pętli "FOR..TO..DO". Załóżmy, że chcemy zrobić program, który będzie 100 razy wypisywał imię użytkownika. Najpierw użytkownik wprowadza imię, a potem zaczyna się pętla, która polega na 100 - krotnym wypisaniu jego imienia schodząc o linie niżej. Stosując tu znaną ci już pętle, można zrobić to w ten sposób.
USES CRT;
VAR
imie:string;
ilosc:longint;
BEGIN
clrscr;
writeln('Jak masz na imię?');
read(imie);
ilosc:=0;
REPEAT
ilosc:=ilosc+1;
writeln(imie);
UNTIL ilosc=100;
readln;
END.
Jak widzimy, pętla jest prosta i nie trzeba jej dogłębnie omawiać. Program wypisze 100 razy imię użytkownika i się wyłączy. Zatem, w pętli tej z góry ustalona jest ilość wykonania instrukcji. Wiemy, że na 100% pętla wykona się 100 razy. Nic nie jest w stanie tego zmienić. Można, zatem, aby było prościej, zastosować pętle "FOR..TO..DO". Najpierw obejrzyjcie program, a potem wyjaśnienia (program wykonuje to, co poprzedni).
USES CRT;
VAR
imie:string;
ilosc:longint;
BEGIN
clrscr;
writeln('Jak masz na imię?');
read(imie);
FOR ilosc:=1 TO 100 DO
BEGIN
writeln(imie);
END;
readln;
END.
Jak widzimy, zmienne pozostają te same, początek też ten sam. Pętla zaczyna się słówkiem "FOR". Jest to jej początek. Po tym następuje przypisanie wartości jakiejś zmiennej. Zauważmy, że przypisujemy wartość dopiero tutaj, a nie przed pętlą. Następnie widzimy słówko "TO" i wpisujemy wartość zmiennej. Wpisaliśmy 100. Ilość ta informuje już nas, że pętla wykonywać będzie się 100 razy. Było to zatem polecenie, ile razy pętla ma się wykonać. Później następuje słówko "DO" i w oddzielnych blokach "BEGIN", "END" wpisujemy polecenia pętli. Najważniejsze jest, że nie wpisujemy tam już czegoś takiego: "ilosc:=ilosc+1;". Jest to zawarte po słowie "FOR". Gdy pojedyncza instrukcja pętli się zakończy, wartość zmiennej "ilosc" przyjmuje wartość +1. Dzięki temu stworzyliśmy program, który mimo, że wygląda inaczej, działa tak jak poprzedni. Stymulując język polski, będzie to wyglądało tak: Od "imie" równa się 1 do 100, rób ... Pamiętać trzeba o kilku ważnych rzeczach. Instrukcje pętli wpisujemy w oddzielne bloki - wielu o tym zapomina. Jak widzimy, pętla ta może się do czegoś przydać.
To w takim razie, po jakiego grzyba, wymyślono pętlę "FOR..DOWNTO..DO"??? Otóż, poprzednia pętla ZWIĘKSZAŁA wartość zmiennej o 1. Natomiast pętla "FOR..DOWNTO..DO" działa identycznie, z tym, że ZMNIEJSZA wartość zmiennej o 1. Programu już myślę, że nie trzeba robić - wszyscy wiedzą, o co chodzi. Zajmijmy się czymś bardziej skomplikowanym.
Na pewno pamiętacie zagnieżdżanie pętli z poprzedniej lekcji. Robiliśmy tam program "tabliczka mnożenia". Spróbujmy zrobić program ten, ale za pomocą omawianej właśnie pętli. Spójrz, jak prościej wygląda on od poprzedniej wersji.
USES CRT;
VAR
a,b:longint;
BEGIN
clrscr;
FOR a:=1 TO 10 DO
BEGIN
FOR b:=1 TO 10 DO
BEGIN
writeln(a,'*',b,'=',a*b);
END;
END;
readln;
END.
Jak widzimy, do tabliczki mnożenia lepiej jest wykorzystywać pętlę "FOR..TO..DO", aniżeli pętle "REPEAT". Ponieważ czas nagli, przechodzimy szybko do drugiej pętli omawianej w tej lekcji. Jest ona najprostsza do zrozumienia. Nie przypomina, bowiem żadnego zawiłego powtarzania, a przejście z jednego miejsca programu do drugiego. Załóżmy, że chcemy, aby program w którymś tam momencie wracał do początku programu lub gdzieś w jego środek. Dla przykładu posłużymy się programem, gdzie użytkownik będzie musiał wpisać hasło (coś już takiego było zdaje się). Jeżeli nie wpisze poprawnego hasła, program powtarza zapytanie. Jeżeli wpisze, program się wyłącza. Można ten program zrobić oczywiście za pomocą innych pętli już ci znanych, ale użyjemy tu nowego polecenia "GOTO" - nie mylić z "GOTOXY". Polecenie to przenosi nas w dowolną część programu. Miejsce, gdzie przenieść ma nas to polecenie, musi być zaznaczone w kodzie programu. Poza tym, tak jak i zmienne - musi być wcześniej zdeklarowane. Miejsce takie nazywa fachowo się "kotwicą" i tak będziemy je nazywać. Deklarować kotwice najlepiej jest zaraz po zmiennych. Zmienne deklarowaliśmy poleceniem "VAR", kotwice natomiast deklaruje się poleceniem "LABEL". W praktyce wygląda to tak:
USES CRT;
VAR
zmienna1:longint;
zmienna2:string;
LABEL miejsce1;
BEGIN
(i tak dalej...)
Jak widzimy, zadeklarowałem dwie zmienne (ale mniejsza z nimi) oraz kotwice o nazwie "miejsce1". Kotwice deklarujemy po słowie "LABEL" i nie wpisujemy żadnych typów (po prostu je wymieniamy po przecinku bez żadnych dwukropków). Na końcu pamiętać trzeba jednak o średniku. Teraz mamy już zadeklarowaną kotwice o nazwie "miejsce1", więc bez problemu możemy ją użyć (a raczej wstawić). Gotowy już program z hasłem, wygląda następująco:
USES CRT;
VAR
haslo:longint;
LABEL miejsce1;
BEGIN
miejsce1:
clrscr;
write('Podaj poprawne hasło: ');
read(haslo);
IF haslo<>123456 THEN goto miejsce1;
writeln('Brawo! Odgadłeś hasło!');
readln;
END.
W powyższym przykładzie kotwica o nazwie "miejsce1" znajduje się na początku programu. Kotwice mogą znajdować się również w innych miejscach. Kotwice wstawia się do programu tylko jeden raz. Wstawiamy jej nazwę i dwukropek. Później komputer czyści ekran i pyta użytkownika o hasło. Hasło jest równe 123456. Jeżeli ktoś wprowadził błędne hasło, komputer wykonuje instrukcję warunkową. W niej ma rozkaz "GOTO miejsce1", co oznacza "idź do miejsce1". Komputer nie patrząc praktycznie na dalszą część kodu, przechodzi do kotwicy tak właśnie oznaczonej. I znowu: czyści ekran, pyta urzytkow... i tak dalej. Zatem, napis z brawami nie ukaże się dopóty użytkownik wprowadzi poprawne hasło (czyli 123456). Na tym właśnie polega polecenie "GOTO".
No i to by było na tyle jeśli chodzi o tą lekcję. Moim zdaniem, jeżeli przeczytałeś już wszystkie wcześniejsze lekcje i tą - jesteś na dobrej drodze, aby zostać programistą. Oczywiście, twoja wiedza jest jeszcze bardzo uboga, dlatego zapraszam do lekcji następnej.
Procedury, procedury z parametrami, funkcje
Doszliśmy w końcu do procedur. Do czegoż one mogą służyć? - pewnie się teraz zastanawiacie. Zaraz wam wytłumaczę. Załóżmy, że chcemy zrobić program, który będzie pytał użytkownika, czy komputer ma wyświetlić na środku ekranu napis. Jeśli użytkownik się zgodzi - napis się wyświetli. Jeżeli użytkownik się nie zgodzi - program pyta jeszcze raz. I znowu kolejny wybór. Program ten wyglądał będzie tak:
USES CRT;
VAR
wybor:longint;
BEGIN
clrscr;
writeln('Czy mam wyświetlić napis? - napisz 1 dla tak lub 2 dla nie');
read(wybor);
IF wybor=1 THEN
BEGIN
gotoxy(10,10);
writeln('Ten napis jest na środku ekranu i zniknie za 5 sekund!');
delay(5000);
Halt;
END;
IF wybor=2 THEN
BEGIN
writeln('Czy mam wyświetlić napis - pytam drugi raz - napisz 1 dla TAK lub 2 dla NIE');
read(wybor);
IF wybor=1 THEN
BEGIN
gotoxy(10,10);
writeln('Ten napis jest na środku ekranu i zniknie za 5 sekund!');
delay(5000);
Halt;
END;
END;
IF wybor=2 THEN
BEGIN
writeln('Nie to nie - trzeci raz nie zapytam');
delay(5000);
Halt;
END;
END.
Jak widzimy, program, aż dwa razy pyta o to samo. Instrukcje polegające na wyświetleniu na środku ekranu napisu są w programie wklepane dwa razy. Czemu zatem nie wpisać tego polecenia tylko jeden raz, a potem w programie się do niego odwoływać? Do tego służy procedura. Jest mile widziana wszędzie tam, gdzie jedna rzecz ma być wykonana kilka razy (lub może być wykonana kilka razy). Najlepiej wpisywać je jeszcze przed głównym programem, a po deklaracji zmiennych itp. Ten sam program, ale z procedurą będzie wyglądał tak:
USES CRT;
VAR
wybor:longint;
PROCEDURE napis;
BEGIN
gotoxy(10,10);
writeln('Ten napis jest na środku ekranu i zniknie za 5 sekund!');
delay(5000);
Halt;
END;
BEGIN
clrscr;
writeln('Czy mam wyświetlić napis? - napisz 1 dla tak lub 2 dla nie');
read(wybor);
IF wybor=1 THEN napis;
IF wybor=2 THEN
BEGIN
writeln('Czy mam wyświetlić napis - pytam drugi raz - napisz 1 dla TAK lub 2 dla NIE');
read(wybor);
IF wybor=1 THEN napis;
END;
IF wybor=2 THEN
BEGIN
writeln('Nie to nie - trzeci raz nie zapytam');
delay(5000);
Halt;
END;
END.
Jak widać, procedurę określa się poprzez słowo "PROCEDURE", a po nim następuje jej nazwa. Następnie wpisujemy średnik i w oddzielnych blokach wypisujemy polecenia w niej zawarte. Później w programie możemy się do niej odwoływać, co spowoduje jej uruchomienie. Daje to nam możliwość zaoszczędzenia pisania jak i estetykę programu. Pomyślcie, jak przydatna jest procedura, gdy w programie trzeba wykonać kilkanaście razy tę samą czynność. Procedury uaktywniamy po prostu wypisując jej nazwę. Procedur w programie może być więcej - wedle gustu. Nawet cały program może być zawarty w oddzielnych procedurach, a w głównej części programu, wymienione tylko ich nazwy, które po kolei się uruchamiają. Możliwości, zatem jest wiele, ale najważniejsze jest, że procedury się przydają i od tej chwili będziemy ich używać. W procedurach, pamiętajcie, że również możecie używać już znanych ci poleceń, pętli i innych rzeczy. Jest to po prostu fragment kodu.
Teraz następna sprawa. Już nie będę jej opisywał na podstawie programu, tylko opowiem. Wszystkie zmienne zadeklarowane przed procedurą słówkiem "VAR" to procedury globalne. Mogą być użyte wszędzie - zarówno w głównym programie jak i w procedurach. Jeżeli chcemy, aby niektóre zmienne używane były tylko w danej procedurze - to deklarujemy je w procedurze, w ten sposób:
VAR
zmienna1,zmienna2:longint;
PROCEDURE pisanie;
VAR
zmienna3,zmienna4:longint;
BEGIN
(polecenia...);
END;
BEGIN
(główna część programu...)
END.
W powyższym fragmencie, "zmienna1" oraz "zmienna2" są to zmienne globalne, czyli mogą być używane zarówno w głównej części programu jak i we wszystkich procedurach. Natomiast "zmienna3" i "zmienna4" to zmienne lokalne - mogą być użyte tylko w aktualnej procedurze (w naszym przypadku jest to procedura "pisanie"). Niektórym zdawać się może, że niepotrzebna jest deklaracja zmiennych lokalnych - lepiej wszystkie umieścić jako globalne i mieć spokój. Pamiętaj jednak, że zmienna globalna zajmuje trochę więcej miejsca w pamięci komputera niż lokalna, poza tym program wtedy wolniej działa. Zatem, jeśli masz niezbyt szybki komputer i zależy ci na pamięci - stosuj zmienne lokalne jeśli jest to tylko możliwe.
AHA! Jeszcze jedno - jeżeli mamy więcej jak jedna procedura - śmiało możemy między nimi się przemieszczać - wpisujemy po prostu nazwę procedury i już - nic prostszego. Nie można tylko stosować polecenia "GOTO" do kotwicy, która nie znajduje się w aktualnej procedurze (bloku "BEGIN" i "END").
A teraz proszę o uwagę i skoncentrowanie się - będzie coś trudnego. Otóż - procedura z parametrami. Aby ją wyjaśnić posłużymy się prostym programem.
Załóżmy, że chcemy napisać program, który będzie wypisywał różne teksty w różnych miejscach na ekranie. Będzie on wyglądał tak:
USES CRT;
BEGIN
GotoXY(10,8);
Write('jakiś tekst numer 1');
GotoXY(42,2);
Write('jakiś tekst numer 2');
GotoXY(30,6);
Write('jakiś tekst numer 3');
GotoXY(13,14);
Write('jakiś tekst numer 4');
GotoXY(63,19);
Write('jakiś tekst numer 5');
Readln;
END.
Jak widać, program wciąż wykonuje jedno i to samo - przesuwa kursor w określone miejsce i wypisuje tekst. Niestety miejsca, gdzie kursor ma się przenieść są różne jak i różne są teksty do wyświetlenia. Użyjemy zatem procedury z parametrem. Nazwiemy ją "pisaz". Procedury takie pisze się tak jak zwykłe, lecz z podanymi parametrami. Wszystko tak właściwie wyjaśni się na podstawie poniższego programu (program wykonuje to co poprzedni).
USES CRT;
PROCEDURE pisaz(x,y:longint; s:string);
BEGIN
GotoXY(x,y);
Write(s);
END;
BEGIN
pisaz(10,8,'jakiś tekst numer 1');
pisaz(42,2,'jakiś tekst numer 2'');
pisaz(30,6,'jakiś tekst numer 3'');
pisaz(13,14,'jakiś tekst numer 4'');
pisaz(63,19,'jakiś tekst numer 5'');
END.
To teraz czas na wyjaśnienie. Po nazwie procedury, w nawiasie wymienione są jej parametry i ich typ (typ taki jak zmiennych). Ważna jest kolejność wypisania. Zauważ, że parametrów nigdzie indziej nie deklarujemy żadnym "VAR". Później rozpoczyna się procedura, która zawiera polecenia z parametrami. W naszym przypadku, mamy 3 parametry. "x" to odległość kursora od lewego rogu ekranu, "y" - od górnego. "s" natomiast jest tekstem do napisania. Po zamknięciu procedury, zaczyna się program. Aby uaktywnić procedurę, wpisuje się jej nazwę oraz w nawiasie wartości parametrów (WAŻNA KOLEJNOŚĆ). Wtedy, komputer przechodzi do procedury i wstawia podane wartości do parametrów. Pierwszy wers głównego bloku ekranu rozkazuje przejść do procedury "pisaz" z trzema następującymi parametrami: 10, 8 oraz "jakiś tekst numer 1". Komputer porównuje wartości z parametrami zadeklarowanymi w nawiasie przy procedurze. Zatem jest to odpowiednio: x=10, y=8, i s=' jakiś tekst numer 1'. Wykonanie poleceń w procedurze jest już tylko formalnością. W ten sposób ułatwiamy sobie życie.
Skoro już procedury zwykłe jak i te z parametrem są ci znane, zajmijmy się funkcjami. Parametry wypisywały tylko jakieś rzeczy, funkcje natomiast dają jakąś wartość. Nie wypisują nic - zwracają tylko wartość. Znaczy to, że mogą przekształcić jakąś wartość na inną, np. użytkownik wprowadzi do funkcji 2, a wyjdzie 4. Może to oznaczać, że funkcja ma zapisane, np. 2+2 albo coś w tym stylu. Mówienie o tym jest dość trudne i ciężko z tego coś pojąć, więc od razu weźmy się za gotowy przykład.
USES CRT;
VAR
a,b:longint;
FUNCTION obliczanie:longint;
BEGIN
obliczanie:=(a+b)*2;
END;
BEGIN
clrscr;
writeln('Podaj pierwszą liczbę');
read(a);
writeln('Podaj drugą liczbę');
read(b);
writeln(' Podwojona suma tych liczb wynosi ',obliczanie);
readln;
END.
Program oblicza podwojoną sumę dwóch dowolnych liczb. Jeżeli wprowadzimy liczby np. 2 i 8, program obliczy 20. Jak widzimy, funkcje również deklarujemy nad programem. Po słowie "FUNCTION" widnieje jej nazwa jak i typ. Tu bardzo ważne: zawsze podajemy typ. Następnie zaczyna się funkcja. Tu kolejna bardzo ważna sprawa. Ponieważ funkcja ma tylko i wyłącznie zwracać jakieś wartości, np. liczby - nie piszcie w funkcji poleceń typu "WRITELN" czy innych bzdet. Zadaniem funkcji jest tylko obliczenie czegoś. W jej wnętrzu, gdzieś musi istnieć przypisanie jej wartości. W naszym przypadku funkcja składa się tylko z jednego wiersza i tym wierszem jest właśnie przypisanie. Jest to najważniejsza i zasadnicza część funkcji. Po to się przypisuje, żeby później w programie komputer wiedział co ma napisać. I tu jeszcze jedna ważna sprawa - funkcji jak widać nie uruchamiamy tak jak procedury, tylko wykonujemy określoną czynność. Nie można więc po prostu sobie jej wstawić, tak jak procedury. Pamiętajmy, że procedura to określony ciąg czynności, a funkcja to tylko jakaś wartość (najczęściej liczbowa). Rozumiemy się?
ZADANIE DOMOWE: Stwórz dowolny program, który składa się z dwóch procedur (jedna z parametrami, a jedna bez) oraz jednej funkcji. Główny blok programu ma najpierw uruchomić obie procedury - jedna pod drugą, a następnie napisać wartość funkcji. Wiem, że nie chce wam się zbyt bardzo robić prac domowych, - ale radzę ich nie omijać. Umiejętność poprawnego wykorzystywania funkcji i procedur pomoże wam w tworzeniu programów jak nikt inny.
Komentarze, zmienne, stałe
To nie powinna być trudna lekcja - dam wam przerwę intelektualną za poprzednią (ależ te funkcje i procedury musiały zamącić wam w głowie). Zacznijmy od komentarzy. Komentarze w programie służą praktycznie do niczego. Komputer je całkowicie ignoruje. W takim razie - po kiego grzyba są te komentarze??? Otóż ktoś wymyślił je dla nas samych. Załóżmy, że mamy dłuuuuugi program. Nie pamiętamy więc gdzie co się zaczyna. Szukanie w stogu siana może być nieco kłopotliwe, dlatego podczas tworzenia długich programów zalecam stosowanie komentarzy. Program nie zwraca na nie uwagi, a my możemy się w nim bardziej zorientować. Przykładowy fragment programu z wykorzystaniem komentarza wygląda tak:
USES CRT;
VAR {Deklaracja zmiennych}
zmienna1:longint;
BEGIN {Początek programu}
clrscr;
writeln('Podaj jakąś liczbę');
read(zmienna1);
writeln('Liczba ta wynosi: ',zmienna1);
readln;
END. {Koniec programu}
Jak każdy widzi, komentarze pisze się w nawiasach sześciennych. Chyba nie muszę tutaj dawać jakichś specjalnych wyjaśnień, dodam tylko, że komentarze również możecie zamieszczać w komentarzach. Wystarczy wszystkie komentarze zawarte w sześciennych nawiasach umieścić w takim oto kwiatku "(*" , a na zakończenie "*)". Czyli jest to nawias zwykły i gwiazda. To tyle jeśli chodzi o temat komentarzy.
A teraz temat stałych. Nie jeden raz pewnie w naszych wszystkich wcześniejszych programach występowały zmienne, które podczas działania programu zachowywały swoją wartość. Jak sama nazwa mówi, "zmienna" to coś co się zmienia. Po co więc stosować zmienne do wartości, które i tak będą ciągle takie same. Takie wartości możemy deklarować poleceniem "CONST", a nazywamy je stałymi. Ich deklaracja ma miejsce przed głównym programem. Nie stosujemy tam żadnych typów - tylko nazwa i wartość. Wartości mogą być różne - najważniejsze to dana liczba bądź tekst, np.:
USES CRT;
CONST
abc=500;
tekst1='jakiś tekst';
BEGIN
polecenia...
END.
Zadeklarowaliśmy 2 stałe: stałą "abc" oraz stałą "tekst1". Pierwsza stała ma wartość 500, więc jak widać można ją wykorzystywać do różnych działań matematycznych. Druga stała ma przypisany tekst. Jej wywołanie w programie da właśnie taki tekst. Stałe wywołuje się tak jak zmienne. Zauważmy jeszcze budowę deklaracji. Nie stosujemy dwukropka jak przy zmiennych, tylko znak równości. Pamiętamy też, że wartość stałej musimy podać w cudzysłowu, jeżeli jest to tekst. Jeżeli chodzi o stałe, to chyba wszystko. Warto moim zdaniem je stosować w programach, gdzie wielokrotnie występuje jakaś liczba. Pomyślcie, co będzie, gdy trzeba będzie tą liczbę zmienić. Zamiast niej, zatem lepiej wstawić stałą, a zmiany późniejsze będą tylko zmianą wartości stałej.
No i ostatni temat - również niezbyt obszerny, - czyli zmienne. Podczas swojej wędrówki wśród wcześniejszych lekcji nauczyłeś się już dwóch typów zmiennych. Były to "longint" oraz "string". Dzisiaj poznasz wszystkie typy (noo prawie wszystkie). Zatem zaczynajmy (poniżej macie typy zmiennych, jakie możecie używać oraz ich krótki opis):
typ LONGINT
Jest to znany ci już typ liczbowy. Nie przejmowaliśmy się zbytnio jego zakresem, gdyż mieści liczby od -2147483648 do 2147483647, więc jak widać powinien każdemu wystarczyć. Jest typem liczb całkowitych i tylko je zapamiętuje.
typ INTEGER
Też jest typem liczb całkowitych, ale o znacznie mniejszym zakresie (-32768..32767). Jeżeli nie potrzebujesz tylu liczb co w typie LONGINT, używaj INTEGER w celu zwiększenia szybkości programu i zaoszczędzenia pamięci.
typ SHORTINT
Czyli krótki typ całkowity. Mieści liczby z przedziału -128, 127.
typ BYTE
Liczba naturalna od 0 do 255. Typ mało stosowany, gdyż nie daje możliwości zapamiętywania liczb ujemnych.
typ WORD
Typ podobny do BYTE, z tym że zapamiętuje liczby z przedziału 0..65535.
typ REAL
Typ liczb rzeczywistych. Liczby rzeczywiste to zarówno ujemne jak i ułamki. Typ ten wydaje się być dobrym typem, poza tym mieści on liczby o wiele większe od typu LONGINT, mimo to związane są z nim pewne problemy. W dalszej części tej lekcji znajduje się akapit dogłębnie omawiający ten typ, więc radzę zajrzeć.
typ STRING
Typ zapamiętujący nie liczbę, a tekst. Nie znaczy to oczywiście, że typ ten nie zapamięta liczb - zapamięta, ale nie jako liczby, a jako ciąg znaków. Typ ten ma jednak swoje ograniczenia - ciąg znaków nie może być dłuższy niż 255 znaków.
typ CHAR
Typ ten działa podobnie jak STRING, z tym, że zapamiętuje tylko 1 znak. Można go interpretować w dwoisty sposób - znak jako znak, albo jako numer w tablicy ASCII. W sumie - wychodzi na jedno i to samo.
Z powyższych typów zmiennych, gdy chcemy robić jakieś skomplikowane obliczenia stosujemy typ REAL. Jak już wspomniałem wiąże się z tym pewien kłopot (a tak właściwie to kilka kłopotów). Po pierwsze, gdy chcemy wprowadzić liczbę typu REAL do komputera, robi się to normalnie. Gorzej już ma się sytuacja, gdy chcemy taką liczbę wyświetlić. Zróbmy program, który najpierw pyta użytkownika o jakąś liczbę, a potem ją wyświetla. Spróbujcie najpierw zrobić ten program wykorzystując zmienną LONGINT lub jakąś inną całkowitą, a potem spróbujcie z REAL. Wynik np. liczby 3 będzie wyglądał miej więcej tak: "3.0000000E+00". Jest to tzw. postać naukowa, dla nas raczej niewygodna. Dlatego właśnie używać należy tu dwukropka. Jeżeli chcemy, aby liczba wyświetlona była "normalnie" podajemy nazwę zmiennej, a następnie dwukropek i jakąś liczbę. Ta liczba będzie decydować, ile miejsc po przecinku ma pokazać komputer. Jeżeli program ma podzielić 1 na 2, wynik bez naszych dekoracji będzie paskudny, więc można napisać: "writeln(1/2:2)". Znaczy to, że program ma napisać ile jest 1 podzielić na 2 korzystając z dwóch miejsc po przecinku. Wynik będzie miej więcej taki "0.50", a nie taki: "0.500000E+00". Chyba ładniej wygląda. Możemy również zastosować jeden dwukropek, liczbę, drugi dwukropek i drugą liczbę. Wtedy pierwsza liczba decydować będzie ile znaków ma być przed przecinkiem, a druga - ile po. Następna sprawa to sposób wprowadzania liczb REAL. Dodatnie liczby wprowadza się normalnie. Jak się pewnie domyślasz - ujemne z minusem na początku. A co jeśli chcemy wprowadzić ułamek, np. 1,5 (półtora)? Zarówno podczas wprowadzania, jak i używania w programach nie stosujemy przecinka tylko KROPKI. Nie pytajcie dlaczego tak jest - po prostu stosuje się kropkę. Kolejna sprawa to tzw. błędy. Wyrażenie 1/3*3, wcale nie jest równe 3, chociaż może się tak wydawać. Jeżeli podzielimy 1 na 3 wyjdzie nam nieskończony ciąg (0,33333333333333333...). Jeżeli teraz pomnożymy to przez 3, jak widać nie ma szans żeby wyszło 3. Trzeba zatem na to uważać. Pamiętaj, że REAL to ułamek dziesiętny, a nie ułamek zwykły. Można również wykorzystać polecenie ROUND, które służy do zaokrąglania liczb. Stosuje się tak jak inne polecenia matematyczne (polecenie ROUND i w nawiasie, to co komputer ma zaokrąglić). Jak widzimy, zmienne typu REAL są dobre, ale trzeba z nimi uważać.
Tablice
Znowu niestety wkraczamy w głębokie wody i zaczynamy dość trudną lekcję. Chodzi mianowicie o tablice. Nie chodzi tu oczywiście o tablicę, po której pisze się kredą, a grupy zmiennych. Określenie to nie jest zbyt fachowe, jednak abyście lepiej sobie mogli wyobrazić, o co chodzi, załóżmy, że są to grupy zmiennych. Jak zwykle, wszystko wyjaśni się na podstawie przykładowego programu. Załóżmy, że użytkownik ma wprowadzić do komputera 20 liczb. Po wprowadzeniu, komputer ma je wyświetlić w odwrotnej kolejności po przecinku. Nie używając jeszcze ci nie znanych tablic, program wyglądał będzie tak:
USES CRT;
VAR
a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20:integer;
BEGIN
clrscr;
writeln('Wprowadź kolejno 20 liczb');
read(a1);
read(a2);
read(a3);
read(a4);
read(a5);
read(a6);
read(a7);
read(a8);
read(a9);
read(a10);
read(a11);
read(a12);
read(a13);
read(a14);
read(a15);
read(a16);
read(a17);
read(a18);
read(a19);
read(a20);
clrscr;
write(a20,',');
write(a19,',');
write(a18,',');
write(a17,',');
write(a16,',');
write(a15,',');
write(a14,',');
write(a13,',');
write(a12,',');
write(a11,',');
write(a10,',');
write(a9,',');
write(a8,',');
write(a7,',');
write(a6,',');
write(a5,',');
write(a4,',');
write(a3,',');
write(a2,',');
write(a1,',');
readln;
END.
Powyższy program ilustruje sposób rozwiązania tego problemu. Sposób ten nie jest jednak zbyt wygodny, gdyż pomyślmy, co by było gdyby użytkownik miał wprowadzić 1000 liczb albo i więcej. Poza tym, zmienne wszystkie są takie same, dodatkowo użyłem podobnych nazw. Czemu zatem, nie skorzystać z tablic. Ten sam program, ale z użyciem tablic wygląda tak:
USES CRT;
VAR
a:array[1..20]of integer;
BEGIN
clrscr;
writeln('Wprowadź kolejno 20 liczb');
read(a[1]);
read(a[2]);
read(a[3]);
read(a[4]);
read(a[5]);
read(a[6]);
read(a[7]);
read(a[8]);
read(a[9]);
read(a[10]);
read(a[11]);
read(a[12]);
read(a[13]);
read(a[14]);
read(a[15]);
read(a[16]);
read(a[17]);
read(a[18]);
read(a[19]);
read(a[20]);
clrscr;
write(a[20],',');
write(a[19],',');
write(a[18],',');
write(a[17],',');
write(a[16],',');
write(a[15],',');
write(a[14],',');
write(a[13],',');
write(a[12],',');
write(a[11],',');
write(a[10],',');
write(a[9],',');
write(a[8],',');
write(a[7],',');
write(a[6],',');
write(a[5],',');
write(a[4],',');
write(a[3],',');
write(a[2],',');
write(a[1],',');
readln;
END.
Tak wyglądał program z użyciem tablic. Tablica ma nazwę "a" i składa się z 20 elementów typu INTEGER. To tak, jak gdyby była grupa 20 tych samych zmiennych, dodatkowo ponumerowanych. Spójrzcie na deklaracje. Po nazwie tablicy następuje dwukropek oraz słówko "ARRAY". Następnie w kwadratowych nawiasach podajemy ich numery: początkowy, dwie kropki oraz końcowy. Na końcu podajemy typ używając dodatkowo słówka "OF". Tak wygląda deklaracja. Tablice używa się podobnie, stosując numer w kwadratowym nawiasie. Jak widzimy, numer w nawiasie ciągle się zwiększa, a w drugiej części programu - zmniejsza. Możemy tu skorzystać z pętli, a numer zastąpić dodatkową zmienną. Spróbujmy, więc nieco uzwięźlić nasz program, aby zajmował mniej miejsca.
USES CRT;
VAR
a:array[1..20]of integer;
k:integer;
BEGIN
clrscr;
writeln('Wprowadź kolejno 20 liczb');
k:=0;
REPEAT
k:=k+1;
read(a[k]);
UNTIL k=20;
clrscr;
REPEAT
write(a[k]);
write(',');
k:=k-1;
UNTIL k=0;
readln;
END.
Z powyższego programu widać, że zamiast licznika, wprowadziłem dodatkową zmienną, nazwaną jako "k". W deklaracji jest osobno podana, gdyż nie można wymieniać po przecinku tablic ze zmiennymi (tylko zmienne). Program korzysta z pętli, w której cały czas zwiększana jest wartość licznika, a co za tym idzie - numer elementu tablicy "a". W drugiej pętli to samo, z tym, że licznik jest zmniejszany. W ten prosty sposób, program nasz działa tak jak poprzednie, a mniej zajmuje. Możemy go jeszcze bardziej zmniejszyć, aż do takiej postaci:
USES CRT;
VAR
a:array[1..20]of integer;
k:integer;
BEGIN
clrscr;
writeln('Wprowadź kolejno 20 liczb');
FOR k:=1 TO 20 DO read(a[k]);
clrscr;
FOR k:=20 DOWNTO 1 DO write(a[k],',');
readln;
END.
Jak widać udało nam się skompresować nasz program do zaledwie kilku linijek tekstu. Porównajcie to teraz z pierwszym programem z tej lekcji, a zobaczycie różnice. W powyższym kodzie, zastosowałem pętlę "FOR". Jak widać, bardzo się tu przydała. Pętla operuje licznikiem "k", czyli jednocześnie numer elementu tablicy. W ten sposób wszystko idzie po kolei i ma swoje miejsce. Zwróćmy uwagę na brak bloków "BEGIN" i "END" przy poleceniach pętli - jeżeli jest tylko jedno polecenie, to bloki są zbędne (ale to na marginesie). Nic więcej tłumaczyć chyba nie muszę.
Pamiętacie coś takiego jak zagnieżdżanie pętli? Po prostu wpisywaliśmy jedną pętlę w drugą. Tak samo można postępować z tablicami, (czyli np. grupa iluś tam elementów, z których każdy składa się z iluś tam). Takie tablice nazywamy tablicami dwuwymiarowymi. Daje to nam bardzo duże możliwości w wszelakich programach. Deklaracja takiej dwuwymiarowej tablicy wygląda przykładowo tak:
a:array[1..10] of array[1..50] of integer;
Jak łatwo się tu domyśleć, mamy tablicę 10-cio elementową, z których każdy z tych elementów składa się z 50 mniejszych elementów. Inaczej mówiąc, razem, mamy 500 elementów posegregowanych w10 grup. Ich wywołanie wykonuje się tak samo jak w zwykłych tablicach, z tym, że w kwadratowym nawiasie należy podać dwie liczby po przecinku. Pierwsza liczby to numer "pierwszego wymiaru", druga - drugiego. Powyżej, pierwszy wymiar składa się z 10 elementów, a drugi z 50. Tak oto stworzyliśmy tablicę dwuwymiarową. Możemy również tworzyć trój, cztero i więcej wymiarowe tablice. Jak widać, tablice dają nam ogromne możliwości.
Instrukcja CASE i readkey
Aby omówić pierwszą z tych instrukcji musicie przypomnieć sobie instrukcję warunkową "IF". Działa ona na wzór: jeżeli warunek jest spełniony, to "wykonuj..". Wiązało to się też z wprowadzaniem różnych zmiennych. Zróbmy program, który będzie pytał użytkownika o jakąś liczbę od 1 do 20. Program będzie mówił, przez ile dana liczba jest podzielna (np. użytkownik wprowadził 4, to program mówi: liczba ta podzielna jest przez 1 , 2 i 4). Aby zrobić ten program, musimy skorzystać z dość dużej ilości instrukcji warunkowych. Będzie on wyglądał mniej więcej tak:
USES CRT;
VAR
liczba:byte;
BEGIN
clrscr;
writeln(' Wprowadź liczbę od 1 do 20');
read(liczba);
IF liczba=1 THEN writeln('Liczba ta dzieli się przez 1');
IF liczba=2 THEN writeln('Liczba ta dzieli się przez 2 i 1');
IF liczba=3 THEN writeln('Liczba ta dzieli się przez 1 i 3');
IF liczba=4 THEN writeln('Liczba ta dzieli się przez 1,2 i 4');
IF liczba=5 THEN writeln('Liczba ta dzieli się przez 1 i 5');
IF liczba=6 THEN writeln('Liczba ta dzieli się przez 1,2,3 i 6');
IF liczba=7 THEN writeln('Liczba ta dzieli się przez 1 i 7');
IF liczba=8 THEN writeln('Liczba ta dzieli się przez 1,2,4 i 8');
IF liczba=9 THEN writeln('Liczba ta dzieli się przez 1,3 i 9');
IF liczba=10 THEN writeln('Liczba ta dzieli się przez 1,2,5 i 10');
IF liczba=11 THEN writeln('Liczba ta dzieli się przez 1 i 11');
IF liczba=12 THEN writeln('Liczba ta dzieli się przez 1,2,4,6 i 12');
IF liczba=13 THEN writeln('Liczba ta dzieli się przez 1 i 13');
IF liczba=14 THEN writeln('Liczba ta dzieli się przez 1,2,7 i 14');
IF liczba=15 THEN writeln('Liczba ta dzieli się przez 1,3,5 i 15');
IF liczba=16 THEN writeln('Liczba ta dzieli się przez 1,2,4,8 i 16');
IF liczba=17 THEN writeln('Liczba ta dzieli się przez 1 i 17');
IF liczba=18 THEN writeln('Liczba ta dzieli się przez 1,2,6,9 i 18');
IF liczba=19 THEN writeln('Liczba ta dzieli się przez 1 i 19');
IF liczba=20 THEN writeln('Liczba ta dzieli się przez 1,2,4,5,10 i 20');
readln;
END.
Jak widzimy - działanie programu jest proste. Zastosowaliśmy tu dwadzieścia instrukcja warunkowych. Dotyczą one tylko jednej zmiennej ("liczba"). Możemy, zatem skorzystać z instrukcji CASE. A zatem, ten sam program będzie wyglądać następująco:
USES CRT;
VAR
liczba:byte;
BEGIN
clrscr;
writeln(' Wprowadź liczbę od 1 do 20');
read(liczba);
CASE liczba OF
1 : writeln('Liczba ta dzieli się przez 1');
2 : writeln('Liczba ta dzieli się przez 2 i 1');
3 : writeln('Liczba ta dzieli się przez 1 i 3');
4 : writeln('Liczba ta dzieli się przez 1,2 i 4');
5 : writeln('Liczba ta dzieli się przez 1 i 5');
6 : writeln('Liczba ta dzieli się przez 1,2,3 i 6');
7 : writeln('Liczba ta dzieli się przez 1 i 7');
8 : writeln('Liczba ta dzieli się przez 1,2,4 i 8');
9 : writeln('Liczba ta dzieli się przez 1,3 i 9');
10 : writeln('Liczba ta dzieli się przez 1,2,5 i 10');
11 : writeln('Liczba ta dzieli się przez 1 i 11');
12 : writeln('Liczba ta dzieli się przez 1,2,4,6 i 12');
13 : writeln('Liczba ta dzieli się przez 1 i 13');
14 : writeln('Liczba ta dzieli się przez 1,2,7 i 14');
15 : writeln('Liczba ta dzieli się przez 1,3,5 i 15');
16 : writeln('Liczba ta dzieli się przez 1,2,4,8 i 16');
17 : writeln('Liczba ta dzieli się przez 1 i 17');
18 : writeln('Liczba ta dzieli się przez 1,2,6,9 i 18');
19 : writeln('Liczba ta dzieli się przez 1 i 19');
20 : writeln('Liczba ta dzieli się przez 1,2,4,5,10 i 20');
readln;
END.
I krótki opis: Po wprowadzeniu zmiennej, piszemy instrukcję "CASE", a po niej nazwę zmiennej. Następnie widać słówko "OF" i zaczynamy pisać wszystkie możliwe wartości zmiennej. Gdy dana wartość będzie się zgadzała, następuje polecenie po dwukropku.
A teraz czas na instrukcję "READKEY", co można sobie tłumaczyć jako pojedynczy klawisz. Jeżeli chcemy zrobić program, który ma pytać użytkownika, czy ten chce wyjść z programu, używamy właśnie "READKEY". Spójrzcie na poniższy program.
USES CRT;
VAR
a:char;
PROCEDURE tekst1;
BEGIN
writeln('Nie wyszłeś z programu');
writeln('Ale i tak program zaraz się wyłączy');
delay(3000);
halt;
END;
BEGIN
clrscr;
writeln('Czy chcesz wyjść z programu [T/N]');
read(a);
IF a='T' THEN halt;
IF a='N' THEN tekst1;
END;
Powyższy program pyta użytkownika, czy ten chce go opuścić. Jeżeli użytkownik wpisze "T", program się wyłączy. Jeżeli użytkownik wpisze "N", program wyświetli tekst zawarty w procedurze. Program ten ma jedną wadę. Użytkownik wprowadzając znak "T" lub "N", musi nacisnąć ENTER. Aby po naciśnięciu żądanego klawisza bez ENTER'A wszystko działało tak jak powyżej, trzeba wykorzystać "READKEY". Wtedy użytkownik nie będzie zmuszony do naciśnięcia klawisza ENTER, a program zatwierdzi jego zmienną zaraz po wyborze literki.
USES CRT;
VAR
a:char;
PROCEDURE tekst1;
BEGIN
writeln('Nie wyszłeś z programu');
writeln('Ale i tak program zaraz się wyłączy');
delay(3000);
halt;
END;
BEGIN
clrscr;
writeln('Czy chcesz wyjść z programu [T/N]');
a:=readkey;
IF a='T' THEN halt;
IF a='N' THEN tekst1;
END;
"READKEY" nie jest jakąś wymyślą procedurą, lecz prostą instrukcję przypisania, po której program od razu się zatrzyma czekając na wprowadzenie zmiennej. No to zrobiliśmy już całkiem niezły program. Warto było by go jeszcze poprawić. Trzeba pamiętać, że w TURBO PASCALU, małe i duże litery to nie to samo, dlatego trzeba się przygotować na ewentualność, że użytkownik walnie małą literę. Poza tym, komputer się pyta "TAK" lub "NIE", więc użytkownik ma tylko te litery wprowadzać. Co będzie, gdy użytkownik wprowadzi np. "S". Na taką ewentualność też trzeba się przygotować. Poprawiony kod, będzie wyglądał tak:
USES CRT;
VAR
a:char;
LABEL kotwica1;
PROCEDURE tekst1;
BEGIN
writeln('Nie wyszłeś z programu');
writeln('Ale i tak program zaraz się wyłączy');
delay(3000);
halt;
END;
BEGIN
clrscr;
writeln('Czy chcesz wyjść z programu [T/N]');
kotwica1:
a:=readkey;
IF (a='T') OR (a='t') THEN halt;
IF (a='N') OR (a='n') THEN tekst1
ELSE goto kotwica1;
END;
W powyższym programie, nie ma znaczenia czy użytkownik wprowadzi małą czy też dużą literę. Zauważcie, że nawet, gdy wprowadzi inną literę, niż pożądane, program nawet nie drgnie, a to dzięki kotwicy. Sposobów na rozwiązanie powyższego problemu jest wiele, ja dałem wam tylko przykład.
Pliki tekstowe
Pliki tekstowe jak każdy wie, zakończone są końcówką TXT. Mogą mieć też inne, dowolne końcówki, ale najlepiej TXT (wtedy bez problemu otwiera je windowsowski notatnik). Zapewne interesuje was myśl "Jak by tu zrobić taki plik"? Można zrobić go ręcznie, i zapewne każdy wie jak to się robi, ale czemu by nie wykorzystać TURBO PASCALA? Na początek nauczysz się, jak się otwiera pliki tekstowe i jak coś do nich zapisać. Najważniejsze jest, że do każdego pliku tekstowego należy utworzyć nową zmienną. My otworzymy sobie jeden plik tekstowy. Zrobimy plik o nazwie "plik1.txt". Mamy już plik tekstowy, teraz czas zająć się jego edycją. Napiszmy, więc program, który zapisze w tym właśnie pliku jakieś zdanie. Jak już wspomniałem - musimy wprowadzić nową zmienną, która będzie kojarzona z tym plikiem. Nazwiemy ją jako "t", a będzie ona typu TEXT (nowy typ). Możemy, zatem już przygotować program w następujący sposób:
USES CRT
; VAR
t:text;
BEGIN
END.
Zmienną mamy, więc już zadeklarowaną, należałoby jeszcze otworzyć plik tekstowy i coś do niego zapisać. Można to zrobić na różne sposoby, zacznijmy, więc od polecenia "ASSIGN". Polecenie to otwiera plik tekstowy. Dokładnie jak to się robi - zobaczysz zaraz na przykładzie. Po poleceniu "ASSIGN", możemy edytować plik, a na końcu zamykamy go poleceniem "CLOSE". Wszystko się wyjaśni na przykładzie:
USES CRT;
VAR
t:text;
BEGIN
assign(t, 'C:\plik1.txt');
Close(t);
END.
Wyżej wymieniony program otwiera plik tekstowy "plik1.txt" i zaraz go zamyka. Po poleceniu "ASSIGN" w nawiasie podajemy zmienną plikową (w naszym przypadku jest to "t"), a zaraz po niej, ścieżkę dostępu i nazwę pliku z końcówką. (Jeśli nie znasz zasad DOS`a, powinieneś od razu wyłączyć ten kurs). Po tym wszystkim następuje zamknięcie nawiasu i oczywiście średnik. Teraz możemy już swobodnie edytować tenże plik, jednak ty tego jeszcze nie umiesz. Bardzo ważne jest, aby po edycji zamknąć dany plik poleceniem CLOSE, gdzie w nawiasie również podajemy zmienną. Tak oto otworzyliśmy plik, i go zaraz potem zamknęliśmy. Teraz należałoby do niego jeszcze coś napisać. Jednak zanim jeszcze to się zrobi, trzeba użyć polecenia "REWRITE". Oznacza ono usunięcie jakiegokolwiek tekstu z tego pliku, aby był on czysty i gotowy do pisania. Uważajcie, zatem z użyciem tego polecenia, gdy w grę wchodzą pliki systemowe. Gdy już zrobimy te wszystkie czynności, możemy śmiało edytować plik poleceniami "WRITE" oraz "WRITELN". Robi się to prawie tak jak normalnie, spójrz zatem w przykład:
USES CRT;
VAR
t:text;
BEGIN
assign(t, 'C:\plik1.txt');
rewrite(t);
writeln(t, 'Jakieś zdanie numer 1');
writeln(t, 'Jakieś zdanie numer 2');
Close(t);
END.
Jak widać polecenie REWRITE też ma nawias, w którym podajemy zmienną plikową. Aby do pliku coś zapisać, musimy w nawiasie przy poleceniach WRITE lub WRITELN podać nazwę zmiennej plikowej, co powie TURBO PASCAL'OWI, że właśnie w tym pliku chcemy dany tekst zapisać. Wydawać ci się może, że mało potrzebne jest stosowanie TURBO PASCALA do otwierania i zapisywania plików tekstowych. Mylisz się. TURBO PASCAL potrafi zrobić rzeczy, na które ty potrzebowałbyś mnóstwa czasu. Na przykład, załóżmy, że potrzebujesz plik tekstowy z wykazem liczb (to znaczy, wypunktowanie do np. 1000). Ręcznie pisząc 1, 2 , 3 , 4..) zajęło by ci to mnóstwo czasu. Można zatem użyć takiego mniej więcej programu:
USES CRT;
VAR
a,liczba:longint;
c:char;
b:text;
label pyt;
BEGIN
ClrScr;
Writeln;
Writeln('Program tworzy plik tekstowy z wykazem liczb!');
Writeln;
Writeln('Ile liczb mam wypisać w pliku wykaz.txt na glownym katalogu dusku c?');
read(a);
writeln;
writeln('Czy na pewno mam wypisac ',a,' liczb? [T/N]');
pyt:
c:=readkey;
IF (c='n') OR (c='N') THEN Halt;
IF (c='t') OR (c='T') THEN
BEGIN
liczba:=1;
Assign(b, 'C:\wykaz.txt');
Rewrite(b);
writeln(b,'');
writeln(b,' Wykaz liczb:');
writeln;
REPEAT
Writeln(b,liczba);
liczba:=liczba+1;
UNTIL liczba=a+1;
Close(b);
Writeln;
Writeln('Zakonczono tworzenie pliku wykaz!');
delay(3000);
Halt;
END
ELSE goto pyt;
END.
No i problem z głowy. Każdy chyba stwierdzi, że zrobienie programu na TURBO PASCAL'U, który stworzy taki wykaz jest o wiele prostsze niż samodzielne pisanie czegoś takiego w notatniku. Spróbujcie uruchomić ten program, a zobaczycie efekt.
Kiedy już umiesz zapisywać pliki tekstowe, warto by było umieć z nich coś odczytywać. Pamiętajcie, że w poprzednich przykładach, dany plik tekstowy wcale nie musiał istnieć. Jeżeli go nie było - TP automatycznie go stwarzał i przygotowywał go zapisu. W sytuacji, kiedy chcemy coś z pliku odczytać, dany plik musi istnieć (inaczej wystąpi błąd). Załóżmy, że chcemy zrobić program, który będzie odczytywał pierwszy znak z pliku tekstowego, a następnie go pokazał w programie. Zrobimy to w ten sposób (uprzednio trzeba stworzyć plik tekstowy, z którego chcemy czytać):
USES CRT;
VAR
t:text;
a:char;
BEGIN
clrscr;
assign(t, 'c:\plik1.txt');
reset(t);
read(t,a);
write(a);
close(t);
delay(3000);
END.
W powyższym programie zadeklarowaliśmy dwie zmienne. Jedna typu TEXT i jedna typu CHAR. TEXT - wiadomo, CHAR natomiast będzie symbolizował literę, którą chcemy odczytać (pierwszą literę z pliku). Otwieramy, zatem plik tekstowy, z którego chcemy czytać. I teraz ważne: nie stosujemy polecenia REWRITE, gdyż skasuje ono wszystko z pliku i już nic nie odczytamy. Stosujemy polecenie RESET i podajemy w nawiasie nazwę zmiennej plikowej. Użycie tego polecenia powoduje ustawienie się kursora na samej górze (na początku pliku), aby można było z niego czytać. Jak widzimy, czytać możemy za pomocą READ. W ten sposób czytamy litery. Wyrażenie "read(t,a);" powoduje odczytanie z pliku skojarzonego ze zmienną "t" jakiegoś znaku. W naszym przypadku jest to znak, który jest na samym początku pliku, gdyż wcześniej zastosowaliśmy RESET. Ponowne polecenie "read(t,a);" da odczytanie kolejnej litery do zmiennej "a". Aby zapamiętać wszystkie litery można zastosować zamiast zmiennej "a" - tablice, ale są jeszcze inne sposoby. Polecenie "write(a);" powoduje tylko wyświetlenie odczytanej litery na ekranie przez 3 sekundy.
A teraz zajmijmy się sytuacją, gdy chcemy, aby wszystkie litery (cały tekst) z pliku były wyświetlone na ekranie. Można zastosować pętlę, ale skąd program ma wiedzieć jak duży jest plik. Poznasz tu, zatem nowe wyrażenie: "EOF", co znaczy "end of file", czyli koniec pliku. Nie jest to żadne polecenie. Program, który odczytuje cały tekst z pliku i wyświetla go na ekranie znajduje się poniżej:
USES CRT;
VAR
t:text;
a:char;
BEGIN
clrscr;
assign(t, 'c:\plik1.txt');
reset(t);
REPEAT
read(t,a);
write(a);
UNTIL EOF(t);
close(t);
delay(3000);
END.
W ten prosty sposób komputer odczytuje kolejno litery z pliku dopóki nastąpi jego koniec. Teraz poznasz również tajemnicze polecenie READLN. Poznasz również drugie ważne wyrażenie: "EOLN", co oznacza "end of line", czyli koniec linii, lub, jak kto woli wiersza. Gdybyśmy zastosowali to w w/w programie zamiast "EOF", program odczytywałby litery aż do końca wiersza. Czemu zatem nie odczytać od razu całego wiersza? Zatem, READLN służy właśnie do tego:
USES CRT;
VAR
t:text;
linia:string;
BEGIN
clrscr;
assign(t, 'C:\plik1.txt');
reset(t);
readln(t,linia);
writeln(linia);
close(t);
delay(3000);
END.
Zamiast zmiennej typu CHAR zastosowaliśmy STRING, (ponieważ wiersz nie składa się z jednej litery). Program odczyta całą linię a potem ją wyświetli. Nie zastosowałem tu "EOLN", gdyż myślę, że już wiesz, o co chodzi.
Dodam jeszcze, że zawsze można otworzyć dwa lub więcej plików na raz. Wystarczy wprowadzić dwie zmienne typu TEXT, a potem dwa razy ASSIGN. Pamiętać trzeba również o zamknięciu i tego i tego pliku.
Istnieje jeszcze polecenie APPEND, ale na razie go sobie zostawimy. Czas na zadanie domowe.
ZADANIE DOMOWE: Zrób program, który odczytuje cały tekst z jednego pliku i zapisuje go do drugiego w odwrotnej kolejności (wskazówka - skorzystaj z tablic). >
Inne polecenia
W tej części kursu poznasz garść kolejnych poleceń, które chociaż nie są szeroko stosowane, jednak warto je znać. Zatem, zaczynajmy:
CHR
Jak pewnie wiesz, każda litera bądź cyfra czy jakikolwiek znak z klawiatury ma swój numer w międzynarodowej tablicy ASCII. Są tam zawarte wszystkie znaki od 1 do 255. Dla przykładu, litera "F" ma numer 70. Zatem "F" można zapisać na dwa sposoby (jako zwykłe "F" lub numer 70 odpowiednio zapisany). Poniższy zapis:
write('F');
Znaczy to samo co:
write(chr(70));
Można to zrobić w jeszcze łatwiejszy sposób, zastępując CHR jako "#", czyli krzyżyk. Jest to zatem:
write(#70);
ORD
Polecenie to działa odwrotnie jak CHR (zamienia znaki na liczby).
write(ord('F'));
Powyższy rozkaz da po prostu liczbę 70.
INC
Jest to instrukcja zwiększająca wartość liczby o 1. Na przykład, gdy jakaś zmienna jest równa 3, zastosowanie INC(nazwa zmiennej) da nam 4. Poza tym, INC działa również na literach (z "a" zrobi się "b" itd.). Przykład jest chyba zbędny.
DEC
Działa odwrotnie do INC, czyli zmniejsza wartość i 1 (działa również na literach).
TEXTCOLOR
Zamienia kolor tekstu na ten, który będzie podany w nawiasie (np. textcolor(red) da nam tekst barwy czerwonej). Dostępne kolory to: black (czarny), blue (niebieski), green (zielony), cyan (turkus), red (czerwony), magenta (karmazynowy), brown (brązowy), lightgray (jasnoszary), darkgray (ciemnoszary), lightblue (jasnoniebieski), lightgreen (jasnozielony), lightcyan (jasny turkus), lightred (jasnoczerwony), lightmagenta (jasnokarmazynowy), yellow (żółty), white (biały - standartowy). Zmiana koloru wymaga modułu CRT.
TEXTBACKGROUND
Czyli zmiana koloru tła (używa się tak jak TEXTCOLOR). Do wybrania możliwe jest osiem kolorów: black (czarny - standartowy), blue (niebieski), green (zielony), cyan (turkus), red (czerwony), magenta (karmazynowy), brown (brązowy), lightgray (jasnoszary). Zmiana koloru tła wymaga modułu CRT.
UPCASE
Polecenie to zamienia małą literę na dużą. Jeżeli użytkownik wprowadzi cyfrę - nie następuje żadna zamiana. Przykłady: UpCase('a') = 'A', UpCase('B') = 'B', UpCase('6') = '6'
STR
Zamienia liczby na zmienne typu STRING. Na przykład, jeżeli chcemy zamienić zmienną o nazwie "a" typu WORD na zmienną o nazwie "x" typu STRING, piszemy: str(a,x) i problem z głowy.
I to chyba koniec dodatkowych poleceń wartych waszej uwagi. Zapraszam do następnej lekcji.
Podsumowanie
I tak oto doszliśmy do samego końca. Każdy dobry programista powinien znać program TURBO PASCAL, gdyż jest to podstawa programowania. Życzę wam udanych programów i innych projektów wykonanych na tym programie. Nie załamujcie się niepowodzeniami, doszukujcie swoich błędów, nie poddawajcie się. Trzeba ćwiczyć, pisać, ciągle uczyć się nowych rzeczy. Pamiętaj, że niniejszy kurs opisuje tylko niewielką część TP i został stworzony dla zupełnie początkujących programistów. Dopiero po kilku tygodniach pisania (a może nawet miesiącach) będziesz mógł wkroczyć w następne etapy informatyki. Powinieneś nauczyć się też C++. Polecam ci również program Delphi. Bardzo pomocny jest tam TURBO PASCAL, gdyż ponad 90% poleceń - to właśnie polecenia TP. Tak naprawdę, Delphi to windows'owy Pascal.
A zatem, nie pozostało mi nic innego, jak życzyć wam powodzenia.
No to na tyle . Napisał Paweł R. pełne imię jest w nazwie mojego chomika na chomikuj.pl Polecam C++ Szkoła Programowania