Rozdział 23-24
Transkrypt
Rozdział 23-24
Trzy ważne słowa Zacznijmy od prostych analogii do przykładów znanych już z części poświęconej Pas calowi. W C, posługując się funkcjami bibliotecznymi, możemy łatwo napisać podob ne programy. Oto przykłady, które demonstrują sposób ustawienia koloru tekstu na ekranie: //<— pisz na czerwono (ustaw kolor tekstu) t e x t c o l o r (RED) ; — oraz koloru tła pod wyprowadzanym tekstem: textbackground(WHITE); // <— tlo tekstu na biało Listing L 2301.C ♦include <stdio.h> ♦include <conio.h> i n t ma i n( ) { c l r s c r (); gotoxy(5, 3); gotoxy(12, 8); gotoxy(32, 18); p u t s ( " X <— Tu: X=5, g e t c h () ; r e t u r n 0; Listing L 2302.C ♦include <std io .h> ♦include <conio.h> i n t mai n () p u t s ( " X <— a t u : p u t s ( " X <— a t u : Y=3"); X=1 2 , X=32, Y=8"); Y=18"); Trzy w ażne sło w a w C { c l r s c r () ; textbackground(WHITE); textcolor(RED); gotoxy(5, 3); c p r i n t f ( " X <— Tu: X=5, Y=3" ) ; // <— cprintff) t e x t b a c k g r o u n d ( YE L L O W ) ; textcolor(BLUE); g o t o x y (7, 4); c p r i n t f ( " X <— a t u : X=7, Y=4"); g e tc h (); r e t u r n 0; } Popatrzmy uważnie na dwa powyższe przykłady i porównajmy je z programami pi sanymi uprzednio w Pascalu. Chociaż nazwy funkcji bibliotecznych są bardzo często takie same lub podobne, istnieje kilka różnic w zapisie: • Nazwy funkcji bibliotecznych C pisze się zawsze małymi literami. • Nazwy stałych w C pisze się wielkimi literami. Paleta kolorów i nazwy są dokładnie takie same. Nawet instrukcja skoku g o t o jest identyczna. Istnieje jednakże pewna różnica. W przeciwieństwie do Pascala, w C/C++ nie musimy deklarować etykiety przed użyciem. Kompilator C rozpoznaje etykietę po dwukropku na końcu, na przykład: etykieta: Instrukcja skoku do miejsca zaznaczonego za pomocą etykiety jest taka sama jak wPascalu (z tym że pisana jest małymi literami): goto nazwa_etykiety; Choć stosowanie instrukcji g o t o nie jest w dobrym tonie i jej wyeliminowanie było jednym z najważniejszych celów towarzyszących wprowadzaniu, popularyzacji i lan sowaniu programowania strukturalnego jako obowiązującego standardu, nie pomijam jej w niniejszym podręczniku. Ma to pewne uzasadnienie. Istotne argumenty są dwa: 1. Kompilatory Pascala, C i C++ mogą generować kod asemblera i pokazywać go w oknie diagnostycznym debugera. Na poziomie asemblera kompilatory same stosują etykiety i instrukcje skoków warunkowych i bezwarunkowych. Programi sta musi rozumieć, na czym one polegają. 2. Przy programowaniu sterowników mikroprocesorowych, w asemblerze i w C czę sto nadal stosuje się instrukcje skoków warunkowych i bezwarunkowych. To nie zbędny element rzemiosła inżynierskiego. ROZDZIAŁ 23 ■ Trzy w ażne sło w a w C Należy pamiętać, że metodyka programowania strukturalnego i obiektowego nie ze zwala na stosowanie skoków g o t o . Żaden z bardziej zaawansowanych przykładów w podręczniku nie zawiera tej instrukcji. Pamiętajmy: nie ma pętli programowej, w któ rej użycie instrukcji skoku g o t o byłoby niezbędne. Każdą pętlę programową można zapisać w sposób strukturalny. Listing L 2303.C /* UWAGA: ta pętla, jak poprzednio w Pascalu, „nie chce” sie zakonczyc! * / #include <std io.h> ł in c l u d e <conio.h> i n t ma i n( ) { i n t k o l o r l = BLACK; // BLACK to czarny i n t k o l o r 2 = BLUE; // BLUE to niebieski c l r s c r () ; gotoxy(30, 1); p u t s ( "S T O P start: [ C t r l ] + [Break] !\n"); // < - - etykieta (początek pętli) textbackground(kolor1++); textcolor(kolor2++); cprintf("X"); g etch {); goto s t a r t ; // < - - instrukcja skoku (koniecpętli) r e t u r n 0; } Nietrudno się domyślić, że funkcja c p r i n t f () to odpowiednik p r i n t f (), tylko w wer sji na konsolę (ang. Console PRINT Formatted output). W notacji C jest jednak kilka różnic: 1 . Deklaracje zmiennych znajdują się wewnątrz funkcji m a i n (). To ważne spostrze żenie. Zmienne w C można zadeklarować przed początkiem programu. Stają się wtedy, jak w Pascalu, zmiennymi globalnymi. Warto zwrócić uwagę, że metodyka programowania strukturalnego zaleca stosowanie możliwie jak najmniejszej licz by zmiennych globalnych. Zastępowanie zmiennych globalnych przez zmienne lokalne jest pożądane i korzystne z powodu bardziej racjonalnego wykorzystania pamięci. Zmienna lokalna zajmuje pamięć tylko na chwilę, a zmienna globalna — na stałe. Trzy w ażne stów a w C 2 . Brak słowa kluczowego V a r . 3. Wiele funkcji bibliotecznych nazywa się tak samo (choć nazwy pisane są małymi literami). . 4 Nawet w tak prostych programach pojawiają się elementy składni charaktery styczne dla C i C++. Kolejny przykład będzie dotyczył inkrementacji zmiennej w pętli programowej. Skró cony zapis: kolorl++; — oznacza w C++: k o l o r l = k o l o r l + 1; Program rzeczywiście wykonuje pętlę, ale ta pętla nie chce się zakończyć! Jeśli znaj dujemy się w środowisku uruchomieniowym IDE, uda nam się ją przerwać, wy starczy nacisnąć Ctrl+Break. Skoro przed chwilą napisano, że każdą pętlę można zapisać w sposób strukturalny, przekształcimy ten program, posługując się słowami do-w hile. Listing L 2304.C #include < std io .h > ł in c l u d e <conio.h> i n t ma i n( ) { i n t k o l o r l = BLACK; i n t k o l o r 2 = BLUE; c l r s c r () ; g o t o x y (30, 1) ; p u t s ( "STOP - [F3] ! \n"); do { textbackground(ko lo rl+ + ); t e x t c o l o r (kolor2) ; c p r i n t f ("X "); g e tc h (); } while (!kbhit()); r e t u r n 0; } Wyjaśnienie rozpocznijmy od konstrukcji pętli: do { ...........} w h i l e ( !kbhit() ); ROZDZIAŁ 23 U Trzy w ażne stów a w C W tłumaczeniu na język polski znaczyłoby to mniej więcej: Powtarzaj P o c z ą t e k . . . . Koniec Dopóki NIE n a c i ś n i ę t o _ k l a w i s z a Słowo kluczowe do jest tu odpowiednikiem pascalowskiego R e p e a t i służy w C/C++ właśnie do tego, by wytłumaczyć, że jakiś fragment kodu powinien być powtarzany. Początek tego fragmentu zaznacza się tym razem nie etykietą, lecz nawiasem klamro wym {. Koniec tegoż fragmentu zaznacza się nawiasem klamrowym }. Pomiędzy oba nawiasy można wstawiać więcej niż jedną instrukcję. To, co znajduje się pomiędzy nawiasami { . . . }, fachowcy nazywają ciałem pętli (ang. loop body), blokiem in strukcji albo instrukcją złożoną. Choć to takie samo słowo kluczowe jak w Pascalu, jego znaczenie i rola są inne Do konstrukcji pętli programowych Pascal potrzebuje słów: F o r , T o , DownTo, Do, whi l e , Natomiast C i C++ stosują tylko trzy słowa: f o r , d o , w h i l e — i już. Trudno uwierzyć, że C lub C++ może być prostszy od Pascala, jednakże w niektórych sytuacjach naprawdę jest. Repeat, U n til. W kodzie z tego przykładu znajduje się jeszcze wywołanie funkcji bibliotecznej: kbhit() // <— czy naciśnięto cos na klawiaturze? Zapis ! k b h i t () oznacza nie naciśnięto klawisza. Znak wykrzyknika spełnia w C/C++ funkcję przeczenia, czyli — jak mawiają fachowcy — realizuje logiczną funkcję nega cji/inwersji NOT (NIE). Samo k b h i t () to nazwa gotowej funkcji bibliotecznej, która sprawdza, czy użytkownik nacisnął jakiś klawisz. Z funkcjonalnego punktu widzenia jest to dokładny odpowiednik pascalowskiego K e y P r e s s e d ( ) . Aby spokojnie prześledzić wszystkie kolory na ekranie, potrzebny nam jeszcze jeden element łamigłówki, mianowicie sposób posługiwania się liczbami. Prościej: potrzeb ne nam są zmienne. Jeśli chcemy posługiwać się zmieniającymi się w trakcie pracy programu liczbami (zmieniać się powinny ich wartości, a nie nazwa czy miejsce w pa mięci), powinniśmy użyć deklaracji. Deklaracja zmiennej, jak w Pascalu, powoduje zarezerwowanie dla niej miejsca w pa mięci, ale nie jest równoznaczna z definicją zmiennej. Zmienne globalne są zerowane przez kompilatory C automatycznie, natomiast początkowa wartość zmiennej lokal nej jest w C nieokreślona. Przed pierwszym użyciem należy zadeklarować i zainicjo wać zmienną. Listing L 2305.C ♦include < std io .h> ♦include <conio.h> i n t m ain( void ) Trzy w ażne stów a w C { // < - deklaracja zmiennej całkowitej i n t X; c l r s c r (); X = 0; do { textbackground(X); textcolor(WHITE); c p r i n t f (" X="); c p r i n t f ( " %d " , X ) ; X++; } while (X <= 1 0 ) ; g e t c h () ; r e t u r n 0; } W przykładzie zmienna X jest licznikiem pętli. Zwróćmy uwagę na sposób wypro wadzania danych charakterystyczny dla wszystkich funkcji z grupy p r i n t f () (jest ich w bibliotekach C/C++ kilka, różnią się pierwszą literą nazwy, np. c p r i n t f O , s p r i n t f ()): c p r i n t f (" X="); cprintf("%d", X); Podkreślmy jeszcze raz różnicę w notacji C Jeśli wyprowadzamy zwyczajny tekst, m o żemy postąpić tak: printf("% s", " t e k s t do w y p r o w a d z e n i a " ) ; lub tak: p r i n t f ( " t e k s t do w y p r o w a d z e n i a " ) ; Znak specjalny formatujący %s oznacza string, czyli łańcuch tekstowy. Jeśli natomiast chcemy wyprowadzać inne dane, na przykład liczby, powinniśmy o tym kompilator C++ poinformować Dlaczego? To proste. Komputery wszystkie informacje w pamięci przechowują w postaci zer i jedynek. Dla przykładu literak zajmuje jeden bajt pamię ci i jest tam zapisana w postaci swojego kodu ASCII, czyli: 0 1 0 0 0 00 1 (dziesiętnie - 65, szesnastkowo - 41, po prostu ’A ’) Skąd komputer ma wiedzieć, co programista życzy sobie zobaczyć na ekranie: 65, 41 czy A? Możemy mu to wytłumaczyć w programie, na przykład tak: c h a r BAJT = ' A ' ; II // < - deklaracja i zainicjowanie zmiennej // <— A ... p r i n t f ("%c", BAJT); (c - character - znak ASCII) ROZDZIAŁ 23 ■ Trzy w ażne sło w a w C printf("% d", BAJT); // <— 65 (d - decimal - dziesietnie) printf("% x", BAJT); // <— 41 (x - hexadecimal - szesnastkowo) Możemy zapisać to samo, posługując się pętlą typu for, co pokazane zostanie w ko lejnym listingu. Listing L 2306.C ♦include < std io .h> ♦include <conio.h> i n t mai n () { i n t X; c l r s c r (); for(X=0; X<=10; X++) I I nagłówek sterujący pętli { t e x t b a c k g r o u n d (X) ; textcolor(X+l); c p r i n t f ("Kolor te k s t u = " ) ; c p r i n t f ( " %d " , X ) ; } g e t c h () ; r e t u r n 0; } Taki zapis w języku C można przetłumaczyć tak: Dl a (X = 0 Dopóki X <= 10 po k a ż d e j p ę t l i i n k r e m e n t u j ą c X = X + 1) Początek kolor tła(N r X ); kolor tekstu(Nr X + 1); d r u k u j na k o n s o l i n a p i s ( " K o l o r t e k s t u = " ) ; d r u k u j na k o n s o l i l i c z b ę d z i e s i ę t n ą . (X); Koniec Konstrukcja języka C: for ( l i c z n i k = w a r t_ p o c z ą tk o w a ; w a r u n e k _ p o w ta r z a n ia ; s k o k _ lic z n ik a ) Trzy w a żn e s ło w a w C — jest typowym nagłówkiem stemjącym pętli programowej (ang. loop control header). Zmienna l i c z n i k (w przykładzie nazywa się x) jest tzw. zmienną sterującą pętli (ang. loop control variable). Powyższy program przykładowy wyprowadza na ekran tekst do kładnie jedenaście razy. J 1. Narysuj schematy blokowe programów przykładowych z tego rozdziału. 2 . Zapisz programy przykładowe z tego rozdziału w Pascalu lub w Delphi. 3 . Pobierz z systemu pomocy przykłady użycia pętli f o r , w h i l e , d o - w h i l e . Skopiuj je, uruchom i spolszcz napisy na ekranie. zjnstrukcje sterujące i instrukcje iteracji W tym rozdziale poznamy grupę instrukcji sterujących (warunkowych): • i f — jeżeli, • i f - e l s e — jeżeli-w przeciwnym wypadku, • sw itch — przełącz, • case — przypadek, wariant, wersja, • break — przerwij, • con tinu e — kontynuuj, — oraz grupę instrukcji iteracji służącą do konstruowania pętli programowych: • fo r, • w hile, • do-w hile. ¡Z 2 4 .1 . Słow o kluczow e if Najpopularniejszą instrukcją warunkową w C++ jest instrukcja i f (jeżeli). Od tej uży wanej w Pascalu różni się tylko tym, że musi być zawsze pisana małymi literami. Słu ży do sprawdzenia, czy warunek jest spełniony, i podjęcia decyzji, czy kontrolowany przez nią blok instrukcji powinien zostać wykonany, czy też nie. Uogólniony format instrukcji jest następujący: if (wyrażenie) { instrukcjal; instrukcja2; 24.1. Sfow o kluczow e if — gdzie w y r a ż e n i e stanowi tzw. kryterium warunkowe. Jeśli wyrażenie zwraca war tość logicznej prawdy (w C logiczna jedynka to predefiniowana, pisana dużymi li terami stała t r u e ) , tzn. warunek jest spełniony, lub też wyrażenie zwraca dowolną wartość niezerową, instrukcja (lub blok instrukcji ujęty w nawiasy { . . . } ) następująca po i f zostanie wykonana. Jeśli natomiast wyrażenie zwróci wartość 0 (co jest inter pretowane jako logiczny fałsz, f a l s e , warunek nie został spełniony), blok instrukcji kontrolowany przez i f zostanie pominięty. Zwróćmy uwagę, że nawiasy { . . .} tworzą blok instrukcji kontrolowany przez in strukcję warunkową i f . Jeśli po i f występuje tylko pojedyncza instrukcja, nawiasy { . . . } mogą zostać pominięte, jednakże nawiasy okrągłe ( . . . ) muszą być stosowane zawsze i ujmować wyrażenie warunkowe. Przykładowo następujące wyrażenie: if (x>0) p r i n t f ( " P i e r w i a s t e k kwadratowy z x w y n o s i : %f \n" , sqrt(x)); oznacza: if (x > 0) // jeśli wartość zmiennej x jest dodatnia, // wywołaj funkcje sqrt(x) i oblicz pierwiastek z wartości x sqrt(x) printf ( " . . . . %f \n" , sqrt(x)); // zwroc wartość pierwiastka I I jako 2 argument funkcji printf() p r i n t f ("Pierw iastek ... wynosi: %f \n" , sqrt(x)); // wydrukuj tekst i wynik zmiennoprzecinkowa (%f) I I jeśli warunek x > 0 nie jest spełniony - nie rob tego, I I lecz przejdz do nastepnej instrukcji. Wyrażenie warunkowe, czyli kryterium, to w tym przypadku wyrażenie rym operator relacji zwróci: ( x > 0 ), w któ • 1 — jeśli wyrażenie jest logicznie prawdziwe (warunek został spełniony), • 0 — jeśli wyrażenie będzie logicznie fałszywe (warunek nie został spełniony). Praktyczne zastosowanie instrukcji warunkowej i f pokażemy na przykładzie progra mu do podejmowania decyzji. Listing L 2401.C łinclude <stdio.h> main () { int i; p r i n t f ( " L i c z b y całk ow ite podzielne i przez 2, i przez 3 \ n " ) ; p r i n t f ( " ( w z a k r e s i e od 0 do 1 0 0 ) : \ n " ) ; for if (i = l ; i<=100; ( (i%2 == 0) i ++) && (i%3 == 0 ) ) p r i n t f ( "%d\n", i'); 197 ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji g e t c h () ; r e t u r n 0; } W wierszu 4 deklarujemy zmienną całkowitą i potrzebną nam jako licznik pętli. W wierszach 5, 6 wyprowadzamy na ekran łańcuchy tekstowe — wyjaśnienie dla użytkownika. W wierszu 7 rozpoczyna się pętla for wykonująca się 100 razy. Analo giczny program zapisany w Pascalu mógłby wyglądać tak jak poniżej: Listing L2402.PAS Us e s C r t ; Va r i : Integer; BEGIN ClrScr; W r i t e L n ( 1L i c z b y c a ł k o w i t e p o d z i e l n e i p r z e z 2 , i przez 3 ' ) ; W r i t e L n ( 1 (w z a k r e s i e od 0 do 1 0 0 ) : ' ) ; For i : = l If To 100 Do ( ( i Mod 2 = 0 ) And ( i Mod 3 = 0 ) ) Then W r i t e L n ( i ) ; ReadLn; END. We wnętrzu ciała pętli instrukcja warunkowa i f sprawdza wartość logiczną wyrażenia warunkowego: ( ( i %2==0) && ( i % 3 = = 0 ) ) W tłumaczeniu na zwykły język oznacza to: Sprawdź, czy reszta z dzielenia przez 2 wynosi 0 i czy jednocześnie reszta z dzielenia przez 3 też wynosi 0. Jeśli wyrażenie zwróci 1 (tzn. dzielenie zmiennej i zarówno przez 2, jak i przez 3 od było się bez reszty), wartość i jest wyprowadzana na ekran przez funkcję printf (). W przeciwnym przypadku instrukcja drukowania zostaje pominięta. Nawiasy { . . . } g jjjg UW AGA Zwróćmy uwagę na następujące zjawiska: • Pętla f o r w C nie ma kroku domyślnego, inkrementacja zmiennej sterującej musi być umieszczona w nagłówku sterującym pętli, na przyktad i++. • Deklaracja zmiennej może w C nastąpić przed kodem programu lub po jego po czątku (zmienna jest globalna lub lokalna dla funkcji m a i n ( ) ) . • Operator iloczynu logicznego (koniunkcji) a n d zapisuje się w C jako &&. • Formatowanie danych i przejście do nowego wiersza jest w W r i t e L n ( ) domyślne, natomiast w p r i n t f ( ) trzeba umieścić znaki sterujące %d, \n. 24.2. Instrukcja w a ru n ko w a if-else w instrukcji warunkowej zostały pominięte, ponieważ i f kontroluje tylko jedną in strukcję (wydruku). Pętli programowej for będziemy przyglądać się stopniowo dalej, ponieważ w C jest to konstrukcja nader ciekawa. Na razie jednakże wróćmy do rozpatrywania innych instrukcji warunkowych. Instrukcja w a run kow a if-else W instrukcji if, jeśli warunek jest spełniony, komputer wykonuje instrukcję kontro lowaną przez tę instrukcję sterującą. Jeśli natomiast wyrażenie warunkowe zwraca 0, następuje przeskok do następnej instrukcji z pominięciem instrukcji wykonywanej warunkowo. Czasem trzeba, by w przypadku niespełnionego warunku komputer wykonał inną operację. Jeśli chcemy postąpić właśnie tak, najwygodniej jest użyć innej instrukcji warunkowej oferowanej przez język C — instrukcji if-else {jeśli tak, to ..., w przeciw nym wypadku, to ...). Uogólniony format tej instrukcji jest następujący: if (wyrażenie) instrukcjal ; instrukcja2; else instrukcja_A; instrukcja_B; — gdzie w y r a ż e n i e stanowi kryterium warunkowe. Jeśli wyrażenie zwraca wartość logicznej prawdy ( t r u e ) , tzn. warunek jest spełniony, to zostanie wykonana instrukcja (lub blok instrukcji) następująca po słowie kluczowym if. Jeśli natomiast wyrażenie zwróci wartość 0 ( f a l s e , warunek nie został spełniony), to zostanie wykonana in strukcja (lub blok instrukcji) następująca po słowie kluczowym else. Praktyczne zastosowanie tej instrukcji warunkowej przedstawia przykład. Listing L 2403.C #include < std io.h> mai n () 1990 ROZDZIAŁ 24 M Instrukcje sterujące i instrukcje iteracji int i; p r i n t f ("Liczby p arzyste: for if (i=0; i<10; Liczby n i e p a rz y ste : \n"); i ++) (i%2 == 0) p r i n t f ( " % d " , e l s e p r i n t f ( "% 20d\n", i); i); r e t u r n 0; } Pętla kontrolowana przez instrukcję f o r wykonuje się 10 razy ( i = 0 - 9). Zgodnie z instrukcją i f - e l s e , jeśli i % 2 == 0 (liczba jest parzysta), to po i f wywoływana jest funkcja p r i n t f () powodująca drukowanie na początku wiersza, bez przejścia do no wego wiersza. Jeśli natomiast wyrażenie warunkowe zwraca 0 (liczba nie jest parzysta), po e l s e wy woływana jest funkcja p r i n t f (), ale specyfikator minimalnej szerokości pola wyj ściowego %2 Od powoduje wyrównanie do prawej w polu wyjściowym i rozsunięcie drukowanych liczb. Zapisy w C i w Pascalu mogłyby wyglądać na przykład tak: / / zapis w C for i) ; (i=0; i<10; i ++) if ( i %2 == 0) p r i n t f < " % d " , i); e l s e p r i n t f ( " %20d\n", { zapis w Pascalu } F o r i : = 0 To 9 Do I f ( i Mod 2 = 0 ) W rite(i) E ls e W riteLn(' i); Chociaż w C instrukcja i f - e l s e jest także traktowana jako pojedyncza instrukcja, przed e l s e w C zawsze stawia się średnik. O tym, że wszystko, co zawiera pętla f o r , jest traktowane jako jedna instrukcja, świadczy brak nawiasów { } w C i pary B e g i n . . . E n d ; W Pascalu. . . Z agnieżdżone 24 3 instrukcje w arunkow e if-else-if Instrukcja i f pozwala podejmować pojedynczą decyzję i dokonywać wyboru typu albo-albo. Często program musi podejmować cały szereg takich decyzji. Można to zrobić za pomocą zagnieżdżonych instrukcji i f (jest to znane z Pascala drzewo decyzyjne lub drabinka decyzyjna). Przykład zagnieżdżania i f przedstawia listing poniżej. Listing L 2404.C #include < std io.h> main () 24.4. Instrukcja sw itch -ca se for (i=-5; if i<=5; i ++) ( i > 0) if (i%2 == 0) printf("%d to liczba parzysta. \n", i); else printf("% d to licz b a nieparzysta. else if \n", i); ( i == 0) printf("To je s t zero. \n"); else p r i n t f ( " L i c z b a uj emna: %d\n", i) ; r e t u r n 0; } Drabinka i f - e l s e - i f wygląda i działa podobnie jak w Pascalu. Jest ona traktowana jako pojedyncza instrukcja, ale: • nie ma w niej słowa Then (w C w ogóle nie ma słowa • wewnątrz przed każdym słowem else Then); znajdują się średniki. Instrukcja sw itch -ca se Można dokonać wyboru jednej z wielu (więcej niż dwóch) możliwości za pomocą za gnieżdżonych instrukcji i f - e l s e - i f . Jeśli jednakże w programie przybywa wariantów i decyzji, takie drabinki stają się bardzo złożone i niezbyt wygodne. Na szczęście w C jest inna instrukcja — s w i t c h (przełącz), za pomocą której można dokonywać wy boru spośród nieograniczonej liczby możliwych wariantów, posługując się wartością wyrażenia warunkowego i wariantami ( c a s e ) . Uogólniony format (składnia) instrukcji s w i t c h - c a s e jest następujący: switch (wyrażenie) c a s e w yrażeniel: instrukcjal; c a s e wyrażenie2: instrukcja2; default: instrukcja-domyślna; Najpierw sprawdzana jest wartość zwracana przez w y r a ż e n i e nazywane wyraże niem sterującym. Jeśli wartość zwrócona przez wyrażenie sterujące jest równa war tości zwróconej przez w y r a ż e n i e l , następuje wykonanie instrukcji i n s t r u k c j a l . Przy czym w y r a ż e n i e l , w y r a ż e n i e 2 są tu wyrażeniami stało wartościowym i (ang. constant expression). Jeśli wartość zwrócona przez wyrażenie sterujące jest równa war ROZDZIAŁ 24 B Instrukcje sterujące i instrukcje iteracji tości zwróconej przez w y r a ż e n i e 2 , następuje wykonanie instrukcji i n s t r u k c j a 2 . Jeśli jednakże wartość zwrócona przez wyrażenie sterujące nie jest równa wartości zwró conej przez żadne spośród wyrażeń (nazywanych także etykietami wariantów — case labet), zostanie wykonana instrukcja domyślna umieszczona po etykiecie d e f a u l t : . Sekwencja instrukcji odnosząca się do każdego spośród wariantów musi rozpoczynać się od słowa kluczowego case. Zwróćmy uwagę, że słowa case tworzą tzw. etykiety i po dobnie jak po wszystkich etykietach w C, musi po nich następować dwukropek (a nie średnik!). Warunkowe wyrażenia stałowartościowe używane w instrukcji switch-case powinny być dobrane w taki sposób, by wzajemnie wykluczały się (tj. by spełniony w danej chwili mógł być tylko jeden wariant). W razie nakładania się wariantów wy konany będzie pierwszy spełniający (licząc od góry). Niektóre kompilatory C++ w razie nakładania się będą generować komunikaty ostrzegające. Nic natomiast nie stoi na przeszkodzie, by wielu wariantom odpowiadało to samo działanie, na przykład: sw itch( X ) { case ' 1 1: case ' 2 1: p r i n t f ( "X = 1 l u b 2 . " ) ; case '3': default: p r i n t f ( "Pozostałe przypadki.. UW AGA Etykiety (ang. label) są używane do zaznaczania pewnych szczególnych miejsc w ko dzie źródłowym programu. W przeciwieństwie do innych języków programowania (ta kich jak np. Pascal czy Delphi), w C + + etykieta nie wymaga odrębnej deklaracji. Stuży do wskazania miejsca, do którego powinien nastąpić skok warunkowy (ang. conditional branch) lub bezwarunkowy (ang. unconditional branch). Listing L 2405.C tinclu de <stdio.h> mai n () ( char dzień; printf("Wpisz printf("(z 1 c y f r ę - numer d n i a " ) , zakresu: dzień = g e t c h a r ( ) ; W 202 od 1 do 3 ) : \ n " ) ; 24.5. Instrukcje break, continue switch (dzień) { case 11 ' : printf("Dzień l\ n "); case '2' : p r i n t f ("Dzień 2 \ n " ) ; case '3 ' : printf("D zień 3\n"); default: } r e t u r n 0; } Oto wydruk programu (dwa uruchomienia): Uruc homi e ni e 1 ( wp i s a ł e m 1 ) : Wpisz 1 c y f r ę - numer d n i a (z z a k r e s u od 1 do 3 ) : Dz i e ń 1 Dz i e ń 2 Dz i e ń 3 Uruchomi eni e 2 ( wpi s a ł e m 2) : Wpisz 1 c y f r ę - numer d n i a (z z a k r e s u od 1 do 3) : Dzi e ń 2 Dz i eń 3 Jak widać na wydruku, najpierw zostało wykonane wybrane wyrażenie ( c a s e : ' l ' : w uruchomieniu 1. i c a s e : ' 2 ' : w uruchomieniu 2.), a następnie wszystkie wyrażenia „w dół”, począwszy od wybranego. Jest to bardzo ważna cecha szczególna instrukcji s w i t c h - c a s e . Aby przerwać w odpowiedniej chwili wykonywanie kolejnych wyrażeń, należy użyć instrukcji b r e a k (przerwij). Instrukcje co ntin ue Na końcu listy instrukcji, której początek jest oznaczony etykietą w obrębie instrukcji s w i t c h - c a s e , można wstawić instrukcję b r e a k . Po wykonaniu takiej listy instrukcji instrukcje znajdujące się poniżej, a oznaczone innymi etykietami typu c a s e n : zosta ną pominięte, a wykonywanie bloku s w i t c h - c a s e zostanie przerwane. W przykła dzie poniżej wykonywane są podobne działania co w programie poprzednim, z tym że została tu zastosowana instrukcja b r e a k . ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji switch (dzień) { case '1': p r i n t f ("Dzień 1 - N i e d z i e l a . \n") ; break; case '2' : printf("D zień 2 - Poniedziałek.\n"); break; case '3': p r i n t f ("Dzień 3 - W to re k . \ n ") ; break; case '4' : printf("Dzień 4 - Środa.\n"); break; case '5' : p r i n t f ("Dzień 5 - Czwartek. \n") ; break; case '6 ' : p r i n t f ("Dzień 6 - P i ą t e k . \ n " ) ; break; case 17 ' : p r i n t f ( "Dzień 7 - S o b o t a . \ n " ) ; break; default: p r i n t f ( " C y f r a s p o z a z a k r e s u od 1 do 7 . \ n " ) ; } Poniżej pokazane zostały trzy rezultaty dialogu z programem z poprzedniego listingu, po umieszczeniu w kodzie takiej zmodyfikowanej instrukcji. Wpisz 1 c y f r ę - numer d n i a (z z a k r e s u od 1 do 7 ) : 1 Dz i eń 1 - N i e d z i e l a . Wpisz 1 c y f r ę - numer d n i a (z z a k r e s u od 1 do 7 ) : 3 Dz i e ń 3 - Wt or e k. Wpisz 1 c y f r ę - numer d n i a (z z a k r e s u od 1 do 7 ) : 24.5. Instrukcje break, continue 9 Cyfra s po z a z a k r e s u od 1 do 7. Dla przykładu, jeśli zmienna c h a r d z i e ń uzyska wartość ' 1 ', po ocenie wartości wy rażenia przełączającego (' l 1) zostanie wykonana następująca sekwencja instrukcji: switch ( dz ie ń) { case '1' : p r i n t f ("Dzień 1 - N i e d z i e l a . \ n " ) ; break; Funkcja p r i n t f () wyprowadzi na ekran napis: Dzień 1 - Niedziela. Komputer przej dzie do wykonania pierwszej instrukcji po nawiasie } kończącym instrukcję s w i t c h . ... 24 5 1 P rzerw anie n ie sko ń czo n e j pętli dzięki in stru kcji b re a k Instrukcje b r e a k i c o n t i n u e funkcjonują także w Pascalu i ich działanie oraz prze znaczenie jest tam identyczne. Instrukcja b r e a k może przerywać nieskończone lub skończone pętle programowe od wewnątrz. Podane poniżej pętle będą wykonywać się bez końca: for (;;) { in s tr li in s tr 2 ; } w h i l e (1) { while ( True) Do Begin in s tr l; in s tr l; in s tr 2 ; in s tr 2 ; } do /* odpowiednik w Pascalu * / End; /* odpowiednik w Pascalu */ R e p e a t { Begin in s tr l; in s tr l; 205 U ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji in s tr 2 ; in s tr 2 ; } End; w hile(l); Until (False); Przykład przerwania nieskończonej pętli za pomocą instrukcji break pokazano na kolejnym listingu. Listing L 2406.C #include < std io.h> m a i n () { char c; p r i n tf(" W p isz znak:\n(znak x + [Enter] while = Koniec)\n"); (1) { c = getc(stdin); if ( c == ' x ' ) break; } printf("Pętla z o s t a ł a przerwana. K o n i e c ! \ n " ) ; r e t u r n 0; } We wnętrzu pętli następuje wczytywanie znaków od użytkownika i zapamiętywanie kodów tych znaków w zmiennej znakowej c. Instrukcja if sprawdza wartość zwraca ną przez wyrażenie (c = = ' x ' ). Jeśli wyrażenie zwróci wartość 1, nastąpi wykonanie instrukcji break. Po przerwaniu pętli komputer wykona pierwszą instrukcję poza pę tlą — funkcja printf () wyprowadzi na ekran komunikat. .. . 24 5 2 In stru kcja c o n tin u e Zamiast przerywać pętlę, czasem trzeba tylko pominąć pewną grupę instrukcji, ale pę tla powinna wykonywać się dalej, czyli być kontynuowana. Do takich celów w języku C służy instrukcja continue. Powoduje ona natychmiastowy skok na początek pętli i podjęcie próby ponownego jej wykonania. Kolejny przykład pokazuje zastosowanie instrukcji continue w programie obliczającym sumy. Listing L 2407.C #include <std io.h> m a i n () 24.6. Pętle p ro g ra m o w e typu for — d o kładniej int i, // sum - to zmienna zawierajaca sume liczb sum; // zmienna i śluzy jako licznik pętli sum = 0; for (i=l; i<8; i ++) { if ( ( i == 3 ) || ( i = = 5 ) ) c o n t i n u e ; sum += i ; } printf("Suma lic z b : 1, 2, 4, 6 oraz 7 wynosi: %d\n", s u m) ; r e t u r n 0; } Oto wydruk tego programu: Suma l i c z b : 1, 2, 4, 6 oraz 7 wynosi: 20 Zastosowanie instrukcji c o n t i n u e powoduje, że liczby 3 i 5 zostają pominięte w su mowaniu. Operator ||to alternatywa (suma logiczna; w Pascalu czy Basicu funkcję tę pełni Or ) . Po zakończeniu wykonania pętli funkcja p r i n t f () wyprowadza na ekran końcową wartość zmiennej sum. .. 24 6 Pętle program ow e typu for — dokładniej Ogólny format instrukcji for for w C jest następujący: ( w y r a ż e n i e l ; w y r a ż e n ie 2 ; w y r a ż e n ie 3 ) in s tr u k c ja l; in s tr u k c ja 2 ; Instrukcja wykorzystuje trzy wyrażenia rozdzielone średnikami. Instrukcje przezna czone do wykonania podczas każdej pętli są ujęte w nawiasy klamrowe, tworząc ciało pętli. W miejscu tym może występować oczywiście i pojedyncza instrukcja. Dozwo lony jest zapis: for ( w l; w2; w3 ) { i n s t r u k c j a l ; in s tr u k c ja 2 ; ... } . 24 6.1. P ętla fo r — s z c z e g ó ły te c h n ic z n e Wykonanie instrukcji f o r rozpoczyna się od wyrażenia w l, w którym następuje zaini cjowanie jednej lub wielu zmiennych. Ważne jest, że w l jest wykonywane tylko jeden raz — na samym początku pętli f o r . Bywa ono nazywane wyrażeniem inicjującym pętli. ROZDZIAŁ 24 M Instrukcje sterujące i instrukcje iteracji w2 to wyrażenie warunkowe. Sprawdzane jest zaraz po wykonaniu wyrażenia w l, a na stępnie — po udanym zakończeniu wykonania każdej pętli. Jeśli w2 zwraca wartość różną od zera, instrukcje stanowiące ciało pętli zostają wykonane. Zazwyczaj wartość niezerowa wynosi tu 1. Jeśli w2 zwróci wartość 0, wykonywanie pętli zostaje przerwa ne, a instrukcja f o r kończy się. Wyrażenie w3 nie jest ani wykonywane, ani oceniane przy pierwszym wejściu do pętli. Jego wartość jest wyznaczana po każdym zakończeniu wykonania ciała pętli — przed przeprowadzeniem oceny wyrażenia w2 i podjęciem decyzji: zakończyć czy wykonać następną iterację pętli. Listing 24 08.C ♦include <std io .h> mai n( ) { int i ; p r i n t f ("Hex(uppercase)\tHex(low erca se )\tDecimal\n"); printf("16-Duze litery\ tl6-m ale litery\tlO \n"); for ( i=0; i<16; i++ ) printf("%X\t\t%x\t\t%d\n", i, i, i); r e t u r n 0; } Program, posługując się specyfikatorami formatu danych %x, %x, %d, przekształca licz by dziesiętne na szesnastkowe, stosując wielkie i małe litery: A - F i a - f. Pierwsze wyrażenie w instrukcji f o r to: i = 0. To instrukcja przypisania, która inicjuje zmienną i , nadając jej początkową wartość 0. Drugie wyrażenie to wyrażenie warunkowe (relacji): i < 1 6 . Zwraca ono wartość l , dopóki jest spełniona relacja i < 1 6. W wyrażeniu tym zastosowany został znany ope rator relacji (<). Wartość przez nie zwracana jest sprawdzana przy pierwszym wejściu do pętli, a następnie po każdym udanym zakończeniu pętli. Trzecie wyrażenie to postinkrementacja i + + . Po każdym wykonaniu bloku instruk cji stanowiących ciało pętli następuje wykonanie wyrażenia w3, czyli powiększenie zmiennej i o 1. W tym przypadku zastosowanie operatora preinkrementacji + + i za miast postinkrementacji i + + (patrz: opis operatorów pre- i postinkrementacji) nie sprawiłoby istotnej różnicy. .. . 24 6 2 In stru kcja p u s ta . Instrukcja f o r nie kończy się średnikiem. Po jej nagłówku następuje albo blok in strukcji, albo pojedyncza instrukcja. Przykładowa instrukcja f o r poniżej zawiera tylko jedną instrukcję jako swoje ciało: 24.6. Pętle p ro g ra m o w e typu fo r — d o kładniej for (i=0; i<8; i ++) suma+=i; Rozważmy teraz działanie instrukcji, w której średnik następuje zaraz po nagłówku pętli f o r : for (i=0; i<8; i++); W języku C jest specjalna instrukcja nazywana instrukcją pustą (ang. nuli statement). Instrukcja pusta nie zawiera niczego oprócz średnika. Innymi słowy, instrukcja pusta to taka instrukcja, która nie zawiera żadnego wyrażenia. Dlatego zapis powyżej ozna cza: „Poczynając od i=0, dodając do i 1 po każdej pętli — wykonuj instrukcję pustą stanowiącą d ało pętli, dopóki i jest mniejsze niż 8”. Aby było to wyraźniej widoczne, przepiszmy powyższą instrukcję tak: for ( i = 0 ; i < 8 ; i ++) Pętla nie będzie zatem robiła niczego, poza samym wykonaniem pętli. W szczegól nych przypadkach może to być uzasadnione (np. opóźnienie), ale w zasadzie jest to typowy błąd. UW AGA Ponieważ instrukcja pusta jest całkowicie legalna w języku C, należy uważać, stawiając średniki, szczególnie w instrukcjach f o r . Dla przykładu, jeśli chcesz napisać pętlę: for (i=0; i<8; i ++) s uma + = i ; — a omyłkowo postawisz średnik po nagłówku instrukcji f o r : for (i=0; i<8; i++); s uma + = i ; — kompilator zaakceptuje to, ale wynik może być całkiem inny od oczekiwanego. ... 24 6 3 D o d a je m y w y ra ż e n ia d o n a g łó w k a p ę tli fo r Język C pozwala umieścić w trzech polach wyrażeń w nagłówku instrukcji f o r więcej wyrażeń. Wyrażenia w obrębie jednego pola należy rozdzielić przecinkami. Dla przy kładu następujący zapis jest w języku C poprawny: for (i=0, j=10; i<10, j>0; i++, j —) ... W polu pierwszego wyrażenia są umieszczone dwa wyrażenia rozdzielone przecin kiem. Są to dwie instrukcje przypisania. Zmienne całkowite i , j są inicjowane z war tościami początkowymi 0 i 10. Wykonanie inicjowania zmiennych odbywa się przy pierwszym wejściu do pętli f o r . ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji Następnie w polu 2 sprawdzane są dwa wyrażenia warunkowe (relacji): i<lO oraz j>0. Jeśli choćby jedno z tych wyrażeń zwraca 0 (warunek nie jest spełniony), wykonanie pętli zostaje przerwane i zakończone Innymi słowy, domyślną relacją dwu warunków jest iloczyn logiczny. Po każdym zakończonym sukcesem wykonaniu ciała pętli wykonywane są inkrementacja i++ oraz dekrementacja j — zawarte w trzecim polu. I teraz znów sprawdzane są warunki: i<lO oraz j> 0, by stwierdzić, czy pętla ma być wykonana następny raz: int i, // j; ... for (i=0, j=8; printf("%d i<8; + %d i++, j —) = %d\n", i, j, i+j); Dodanie do pól nagłówka pętli for dodatkowych wyrażeń stanowi bardzo wygodną metodę manipulowania wieloma zmiennymi: for (i=0, j= l; i<8; printf("%d Wyrażenia for i++, %d w l , w2, w3 j ++) %d\n", j, i, j —i ) ; w nagłówku sterującym pętli: ( w l ; w2; w3 ) — są opcjonalne Każde z tych wyrażeń może zostać pom inięte Wartością domyślną pola wyrażenia warunkowego jest logiczna jedynka, t r u e . Jeśli zastosujemy instrukcję f o r tak: for ( ; ; ) { / * blok instrukcji * / } — powstanie pętla, która będzie wykonywać się bez końca. W trzech polach nagłówka pętli nie ma żadnych wyrażeń. char c; for ( c=' c != 'x'; ) { c = getc(stdin); putchar(c); } Wyrażenia trzeciego brak, tym niemniej pętla wczytuje po jednym znaku od użytkow nika i wyprowadza ten znak na ekran, dopóki użytkownik nie naciśnie klawisza ze znakiem „ x ” (mała litera x). . . Instrukcja 24 7 pętli w hile Instrukcja while jest także używana w C do tworzenia pętli programowych. W prze ciwieństwie do nagłówka pętli for, w nagłówku pętli while jest tylko jedno pole wyrażenia. Uogólniony format instrukcji while jest następujący: 24.7. Instrukcja pętli while in s tr u k c ja l; in s tr u k c ja 2 ; } — gdzie wyrażenie w stanowi warunek wykonania / kontynuacji pętli. Najpierw sprawdzane jest w. Jeśli zwraca wartość niezerową, wykonanie pętli jest kontynu owane, tzn. wykonywane są instrukcje stanowiące ciało pętli. Po wykonaniu wyraże nie jest sprawdzane ponownie. Jeśli wyrażenie ponownie zwróci wartość niezerową, wykonanie ciała pętli zostanie powtórzone Pętla jest powtarzana aż do chwili, gdy przy kolejnym sprawdzeniu wyrażenie zwróci wartość 0. Jeśli po nagłówku w hile na stępuje pojedyncza instrukcja, nie muszą być stosowane nawiasy { . . . } obejmujące blok instrukcji. Oto przykład zastosowania pętli char c = ' '; printf("W pisz while (c while: znak:\n(x - ko n iec. ) \n"); ! = ' x 1) c = getc(stdin); putchar(c); } Pętla w h i l e też może trwać bez końca. Można ją zapisać tak, aby warunek był zawsze spełniony (wyrażenie zawsze zwracało 1): while (1) in s tr u k c ja l; in s tr u k c ja 2 ; > Najczęściej jednakże pętla w hile jest stosowana z typowymi trzema wyrażeniami: int i ; / / deklaracja zmiennej stemjacej i = 1; // w l: inicjowanie zmiennej stemjacej while ( i c l OO ) instrukcj a l ; instrukcj a2; // w2: warunek kontynuacji ROZDZIAŁ 24 B Instrukcje sterujące i instrukcje iteracji // w3: inkrementacja zmiennej sterującej i++; ) Zwróćmy uwagę na typowe rozmieszczenie wyrażeń. Przed pętlą znajduje się wyraże nie w i. Bezpośrednio po słowie w h i l e pojawia się wyrażenie w2. Z kolei wyrażenie w3 znajduje się wewnątrz ciała pętli, zazwyczaj w ostatniej instrukcji. W pętlach f o r i w h i l e wyrażenia warunkowe znajdują się w nagłówku pętli. W pętli — odwrotnie, wyrażenie warunkowe znajduje się na końcu pętli. Dzięki temu instrukcje stanowiące ciało takiej pętli będą zawsze wykonane choćby jeden raz (zanim jeszcze dojdzie do sprawdzania warunku). Natomiast w pętlach f o r i w h i l e , jeśli warunek nie zostanie spełniony (a sprawdzany jest jeszcze przed pierwszym wy konaniem pętli), instrukcje stanowiące ciało pętli mogą nie zostać wykonane ani razu. Uogólniony format instrukcji d o - w h i l e jest następujący: do-w hile do { in s tr u k c ja l; in s tr u k c ja 2 ; } while ( w) ; — gdzie w jest sprawdzane w celu ustalenia, czy warunek jest nadal spełniony i czy instrukcje stanowiące ciało pętli powinny zostać wykonane kolejny raz. Jeśli wzwraca wartość niezerową, wykonanie pętli jest kontynuowane W przeciwnym razie wyko nanie pętli zostaje zakończone. Zwróćmy uwagę, że instrukcja d o - w h i l e jest zakończona średnikiem, co w istotny sposób odróżnia ją od instrukcji i f oraz od instrukcji w h i l e . Przykładowy program poniżej drukuje na ekranie znaki od A do G, stosując pętlę d o - w h i l e do powtarzania drukowania. Listing 2409.C łin clud e <stdio.h> m a i n () { int i; i = 65; // wyrażenie inicjujące - przed pętla do { p r i n t f ( " K o d ASCI I znaku %c t o : %d. \n" , i, i); 24.8. Pętla d o -w h ile i++; } while ( i<72 ); r e t u r n 0; } Po uruchomieniu program wyprowadził na ekran następujący tekst: Kod ASCII znaku A t o : 65. Kod ASCII znaku B t o : 66. Kod ASCII znaku G t o : 7 1 . Mamy tu 3 typowe wyrażenia. We wszystkich trzech pętlach w C/C++ występuje: • wyrażenie inicjujące zmienną sterującą, np. i = 1, • wyrażenie warunkowe (warunek wykonania pętli), np. i < 10, • wyrażenie inkrementacji/dekrementacji (krok pętli), np. i++. Po zastosowaniu dodatkowo słów b r e a k , c o n t i n u e za pomocą tych trzech słów klu czowych języka C można skonstruować każdą pętlę programową. Wstawienie jednej pętli do wnętrza innej pętli nazywa się zagnieżdżaniem (ang. nested loops). Przypomina to trochę zasadę zagnieżdżania nawiasów. Komputer będzie zawsze wykonywał pętle wewnętrzne, a dopiero po ich zakończeniu wykona następny cykl pętli zewnętrznej. Przykład przedstawia listing poniżej. Listing 24 1 0 .C #include < std io .h> main () { int i, for j; (i=l; i<=3; i ++) / * pętla zewnetrzna * / { p r i n t f ("Start p ę tli for ( j = 1; p r i n t f (" p r i n t f (" j<=4; z e w n e t r z n e j . Numer p ę t l i i); /* pętla wewnetrzna * / j ++ ) Cykl Nr %d p ę t l i w e w n e t r z n e j . \ n " , j ) ; Koniec p ę t l i z e w n e t r z n e j Nr Z%d. \n", } return 0; } Wydruk wykonany przez program wygląda tak: Start p ętli Z%d. \n", zewnetrznej. Numer p ę t l i : Zl. i); ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji Cykl Nr 1 p ę t l i w e w n e t r z n e j . Cykl Nr 2 p ę t l i w e w n e t r z n e j . Cykl Nr 3 p ę t l i w e w n e t r z n e j . Cykl Nr 4 p ę t l i w e w n e t r z n e j . Koniec p ę t l i Start p ętli z e w n e t r z n e j Nr Z l . zewnetrznej. Numer p ę t l i : Z2. C y kl Nr 1 p ę t l i w e w n e t r z n e j . Cykl Nr 2 p ę t l i w e w n e t r z n e j . Cykl Nr 3 p ę t l i w e w n e t r z n e j . Cykl Nr 4 p ę t l i w e w n e t r z n e j . Koniec p ę t l i Start p ę tli z e w n e t r z n e j Nr Z2. zewnetrznej. Numer p ę t l i : Z3. Cykl Nr 1 p ę t l i w e w n e t r z n e j . Cykl Nr 2 p ę t l i w e w n e t r z n e j . Cykl Nr 3 p ę t l i w e w n e t r z n e j . Cykl Nr 4 p ę t l i w e w n e t r z n e j . Koniec p ę t l i z e w n e t r z n e j Nr Z3. Z wydruku widać, że zanim rozpocznie się kolejna iteracja pętli zewnętrznej, musi zostać zakończone wykonywanie pętli wewnętrznej. Gdy rozpocznie się wykonanie następnego cyklu pętli zewnętrznej, pętla wewnętrzna jest ponownie wykonywana zadaną liczbę razy. Na wydruku dobrze widać kolejność wykonywania pętli zewnętrz nych i wewnętrznych. Ciekawe może być tu porównanie typowej notacji dwu popularnych języków progra mowania — Pascala i C W tabeli 24.1 porównano instrukcje warunkowe i pętle. Tabela 24.1. Porównanie instrukcji warunkowych i pętli Język Pascal Język C Uses C r t ; #include < st d i o .h > Label S t a r t , Koniec; #i n c l u d e < c o n i o . h > Var N, Suma : I n t e g e r ; i n t n, BEGIN main () ClrScr; WriteLn( 'T e s t 5 p ę t l i : Suma : = 0 ; N : = 1; start: Suma : = Suma + N; suma; { ' ); c l r s c r (); p u ts ( "Test 5 p ę t l i : suma = 0 ; n = 1; start- 24.8. Pętla d o -w h ile N := N + 1; suma += n; I f ( N > 10 ) Then GoTo K o n i e c n++; El s e Goto S t a r t ; if ( n > 10 ) g o t o k o n i e c ; e l s e goto s t a r t ; Koni ec: Wr i t e L n ( ' Wynik: ', Suma ) ; koniec: Suma : = 0 ; p r i n t f ( "Wynik: %d \n" , For N : = 1 To 10 Do Suma : = Suma + N; suma = 0; W r i t e L n ( 'Wynik: ', Suma ) ; for (n = 1, suma = 0 ; Suma : = 0; N : = 1 ; suma = suma + n + + ) ; While p r i n t f ( "Wynik: ( N <= 10 ) Do suma = 0 ; Begin Suma : = Suma + N; while N : = N + 1; { n <= 1 0; %d \n" , suma ) ; n = 1; ( n <= 10 ) suma += n; End; W r i t e L n ( ' Wynik: ', n++; Suma ) ; Suma : = 0 ; N : = 1; } Repeat p r i n t f ( "Wynik: Begi n suma = 0 ; Suma : = Suma + N; do N : = N + 1; { %d \ n" , suma ) ; n = 1; suma += n; End; Until n++; ( N > 10 ) ; W r i t e L n { ' Wynik: ', Suma ) ; Whi l e } while ( n <= 10 ) ; p r i n t f ( "Wynik: Suma : = 0; N : = 1; while ( 1 ) N : = N + 1; suma += n; If n++; ( N <= 10 ) Then Co n t i nu e if E l s e Break; ( n <= 10 ) c o n t i n u e ; e l s e break; End; ReadKey; suma ) ; { Suma : = Suma + N; W r i t e L n ( ' Wynik: %d \n" , suma = 0 ; n = 1; ( True ) Do Begin END. suma ) ; ', Suma ) ; } p r i n t f ( "Wynik: %d " , g e t c h () ; re t u r n 0; suma ) ; ROZDZIAŁ 24 ■ Instrukcje sterujące i instrukcje iteracji Choć to, co jest w C słowem kluczowym (np. break/continue), w Pascalu okazuje się na przykład procedurą biblioteczną, teksty programów zamieszczonych w tabelce ą w obu językach dalece podobne, a działanie — identyczne. | Ć W IC Z E N IA 1 . Dane: x = 0. Czy operacje arytmetyczne objęte poniższą instrukcją warun kową zostaną wykonane? if (x != 0) y = 1234 / x + 4 5 6 7 ; 2 . Dane: x = 4 , y = 2 , o p e r a t o r = 1 J aka będzie końcowa wartość zmiennej x po wykonaniu poniższej instrukcji s w i t c h ? switch(operator) { case '+': x += y ; case '-': x -= y ; case ' * 1 : x *= y ; case '/': default x / - y; : break; } 3 . Dane: x = 4, y = 2 , o p e r a t o r = ' - ' . Jaka będzie końcowa wartość zmien nej x po wykonaniu poniższej instrukcji s w i t c h ? switch(operator) { case x += y ; b r e a k ; case x -= y; break; case x *= y ; b r e a k ; case x /= y ; b r e a k ; default : break; } 4 . Narysuj schemat blokowy kodu z zadania 3. Zapisz analogiczny kod w Pascalu. q .2 i 6