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

Podobne dokumenty