Pętla repetycyjna
Pętla repetycyjna (pętla warunkowa) w programowaniu, to rodzaj pętli, w której wykonanie kolejnej iteracji uzależnione jest od pewnego, zdefiniowanego przez programistę warunku. Warunek zawarty w definiowanej pętli jest pewnym wyrażeniem, które zwraca wartość typu logicznego (np. Pascal[1][2], Visual Basic[3], VBA[4]). Istnieją języki programowania, w których składnia nie przewiduje takiego typu danych. W językach tych stosuje się wyrażenia zwracające pewną wartość innego typu, która następnie podlega odpowiedniej interpretacji, np. wartość zero może być utożsamiana z wartością false typu logicznego, a pozostałe wartości z wartością true , lub inne rozwiązania (np. PL/I[5][6], C[7][8][9][10], C++[9][11] i pochodne). W zależności do tego, czy wartość logiczna, uzyskana w wyniku ewaluacji wyrażenia reprezentującego warunek, jest równa wartości logicznej true (prawda), czy false (fałsz), wykonywanie pętli jest kontynuowane, bądź przerywane.
Wyrażenia warunkowe
Jak wyżej zaznaczono, pętla repetycyjna definiowana jest za pomocą określonego wyrażenia, które określa czy ma nastąpić przejście do kolejnej iteracji, czy też ma zostać zakończone wykonywane pętli i w konsekwencji ma nastąpić przejście do kolejnej instrukcji umieszczonej za daną pętlą. Zapis wyrażenia, oraz typ wartości wyrażenia, zależny jest od składni konkretnego języka programowania. Powszechnym jest zapis wyrażeń kontrolnych analogicznie do zapisu tych wyrażeń dla instrukcji warunkowej. Szczególne znaczenie mają w tym przypadku operatory porównań, choć warunek może zostać wyrażony także całkiem inaczej, np. jako wywołanie funkcji zwracającej wartość logiczną, bądź jako identyfikator zmiennej logicznej, której wcześniej przypisano rezultat ewaluacji wyrażenia warunkowego. Powszechna jest również w językach programowania dostępność operatorów logicznych, umożliwiających budowanie warunków złożonych z kilku warunków łącznych lub alternatywnych (ewentualnie mogą w konkretnym języku być dostępne inne operatory logiczne, np. alternatywy wykluczającej czy implikacji). Ponadto operator logiczny realizujący operację negacji pozwana na rekompensatę ewentualnego braku pętli powtarzanej przy spełnieniu lub niespełnieniu warunku, gdyż zastosowanie tego operatora do podanego warunku jest równoważne zastosowaniu frazy przeciwnej.
Wybrane przypadki wyrażeń warunkowych (przykłady w Turbo Pascalu[2])
warunek złożony
|
użycie zmiennej
|
powtarzaj gdy warunek nie spełniony (sprawdzany na początku pętli) alternatywny wobec braku odpowiedniej instrukcji
|
while (a<b) and ((b>c) or (b>d)) do
begin
{ instrukcje pętli }
end;
|
var logic : Boolean;
begin
repeat
{ instrukcje pętli 1 }
logic:=(a<b) xor (b>c);
{ instrukcje pętli 2 }
until logic;
end.
|
while not (a>=b) do
begin
{ instrukcje pętli }
end;
|
Warunki kontynuacji bądź zaniechania wykonywania pętli
W różnych językach programowania stosowane są warunki, które decydują o kontynuacji wykonywania pętli lub jej przerwania, w następujący sposób:
- pętla jest kontynuowana gdy warunek jest spełniony (
true ), a przerywana gdy nie (false ), lub odwrotnie
- pętla jest kontynuowana gdy warunek nie jest spełniony (
false ), a przerywana gdy jest spełniony (true ).
Porównanie pętli i kodu z użyciem instrukcji warunkowych oraz skoku na przykładzie języka Visual Basic[3] i VBA[4]
miejsce sprawdzania warunku
|
przypadek
|
kod z użyciem pętli
|
kod "zastępczy"
|
sprawdzanie warunku na początku pętli
|
powtarzaj, gdy warunek spełniony
|
Do While warunek
' treść pętli
Loop
|
start: If Not warunek Then Goto koniec
' treść pętli
Goto start
koniec: ' koniec pętli
|
powtarzaj, gdy warunek nie spełniony
|
Do Until warunek
' treść pętli
Loop
|
start: If warunek Then Goto koniec
' treść pętli
Goto start
koniec: ' koniec pętli
|
sprawdzanie warunku na końcu pętli
|
powtarzaj, gdy warunek spełniony
|
Do
' treść pętli
Loop While warunek
|
start:
' treść pętli
If warunek Then Goto start
' koniec pętli
|
powtarzaj, gdy warunek nie spełniony
|
Do
' treść pętli
Loop Until warunek
|
start:
' treść pętli
If Not warunek Then Goto start
' koniec pętli
|
Miejsce sprawdzania warunków
Warunki decydujące o kontynuacji lub zaprzestaniu wykonywania pętli mogą być sprawdzane:
- na początku pętli, przed wykonaniem pierwszej instrukcji zawartej w bloku definiowanej pętli,
- wewnątrz pętli, w jej bloku, po wykonaniu części instrukcji, a przed wykonaniem pozostałych,
- na końcu pętli, po wykonaniu wszystkich instrukcji zawartych w bloku definiowanej pętli.
Jeżeli warunek jest sprawdzany na początku pętli, to może nastąpić taka sytuacja, że instrukcje zawarte w pętli nigdy nie zostaną wykonane. Będzie to miało miejsce w sytuacji, gdy przy pierwszym wykonaniu warunek nie będzie spełniony (lub odwrotnie, w zależności od rodzaju pętli – zobacz wyżej). Inaczej jest, gdy warunek jest sprawdzany na końcu pętli. W tym przypadku instrukcje zawarte w pętli zostaną wykonane co najmniej jeden raz. Natomiast, jeżeli warunek jest sprawdzany wewnątrz pętli mamy sytuację stanowiącą połączanie obu powyższych przypadków. Mianowicie instrukcje zapisane przed sprawdzeniem warunku, zostaną zawsze wykonane co najmniej jeden raz, a instrukcje zapisane po warunku sprawdzającym, mogą nie zostać wykonane ani jeden raz.
Porównanie wyników programu dla różnych miejsc sprawdzania spełnienia warunku w pętli repetycyjnej (przykłady w języku C[7][8][9][10])
miejsce sprawdzania warunku
|
na początku
|
wewnątrz
|
na końcu
|
przykład
|
#define MIN=4
int a;
scanf("a=%d",a);
while(MIN>=a)
{
printf("Teraz a=%d\n\r",a++);
printf("Teraz a=%d\n\r",a++);
}
|
#define MIN=4
int a;
scanf("a=%d",a);
while(1)
{
printf("Teraz a=%d\n\r",a++);
if (!(MIN>=a)) break;
printf("Teraz a=%d\n\r",a++);
}
|
#define MIN=4
int a;
scanf("a=%d",a);
do
printf("Teraz a=%d\n\r",a++);
printf("Teraz a=%d\n\r",a++);
while(MIN>=a)
|
wartość zmiennej a
|
1
|
3
|
5
|
1
|
3
|
5
|
1
|
3
|
5
|
wyniki
|
Teraz a=1 Teraz a=2 Teraz a=3 Teraz a=4
|
Teraz a=3 Teraz a=4
|
|
Teraz a=1 Teraz a=2 Teraz a=3 Teraz a=4 Teraz a=5
|
Teraz a=3 Teraz a=4 Teraz a=5
|
Teraz a=5
|
Teraz a=1 Teraz a=2 Teraz a=3 Teraz a=4
|
Teraz a=3 Teraz a=4
|
Teraz a=5 Teraz a=6
|
Zazwyczaj w danym języku programowania zdefiniowane w składni konstrukcje pętli repetycyjnych są tak określone, że jest możliwe sprawdzenie jedynie warunku albo na początku, albo na końcu pętli – nie ma w tym przypadku możliwości zdefiniowania warunków sprawdzanych zarówno na początku, jak i na końcu pętli (np. C[7][8][9][10], C++[9][11], Pascal[1][2]). Inaczej jest jednak, gdy zdefiniowana jest w języku jedna konstrukcja pętli, w której można definiować warunki za pomocą opcjonalnych fraz instrukcji, tak jak zostało to przyjęte np. w języku PL/I[5][6].
Porównanie: PL/I – C, C++
PL/I[5][6]
|
C[7][8][9][10], C++[9][11]
|
DO WHILE A<B UNTIL C>B;
/* instrukcje pętli */
/* brak konieczności stosowania
instrukcji warunkowej i opuszczenia
wszystkie warunki zdefiniowane w nagłówku
pętli za pomocą odpowiednich fraz */
END;
|
while(a<b)
{
/* instrukcje pętli */
/* sprawdzenie dodatkowego warunku
na końcu pętli wymaga użycia
instrukcji warunkowej i opuszczenia */
if(!(c>b)) break;
}
|
Także rzadko występującą możliwością konstruowania pętli jest możliwość jej kontynuowania po zakończeniu bieżącego warunku, już dla innego, kolejnego warunku.
Przykład w PL/I[5][6]:
DO WHILE A<B UNTIL C>B, WHILE D<B, UNTIL D>A;
/* instrukcje pętli */
/* wykonanie pętli nastąpi kolejno dla 3 niezależnych warunków:
– dla A<B (warunek sprawdzany na początku pętli) i równocześnie C>B (ale warunek sprawdzany na końcu pętli),
– a po zakończeniu pętli dla powyższych warunków, dla D<B (warunek sprawdzany na początku pętli),
– i następnie dla D>A (warunek sprawdzany na końcu pętli) */
END;
O sposobie i miejscu zapisu warunków sprawdzających decyduje składnia danego języka programowania. Dla warunków sprawdzanych wewnątrz bloku instrukcji definiujących kolejne iteracje, zapis zawarty jest w ciągu tych instrukcji (np. Ada[12][13], Forth[14][15]). Natomiast dla warunków sprawdzanych na początku i końcu pętli spotyka się rozwiązania, w których albo warunki zapisywane są odpowiednio w miejscu ich wykonywania, tj. na początku i na końcu (np. C[7][8][9][10], C++[9][11], Pascal[1][2], Modula-2[16], Visual Basic[3], VBA[4] i wiele innych), albo rzadziej wszystkie warunki, także te sprawdzane na końcu pętli, definiowane są na początku pętli, w jej nagłówku, w jednym miejscu określającym sposób kolejnych iteracji (np. PL/I[5][6]). W językach programowania, w których nie ma konstrukcji do sprawdzania warunku wewnątrz bloku pętli, dostępne są często instrukcje umożliwiające zmianę przebiegu wykonywania pętli, takie jak instrukcja opuszczenia czy instrukcja kontynuacji (np. C[7][8][9][10], C++[9][11]: break , continue ), które stosowane w połączeniu z instrukcją warunkową lub wyboru (np. C[7][8][9][10], C++[9][11]: if , switch ), zapewniają praktycznie równorzędne środki sterowania przebiegiem realizacji algorytmu.
Porównanie konstrukcji językowych z wbudowanym sprawdzeniem warunku wewnątrz pętli i odpowiadających im konstrukcji, gdy język nie przewiduje takich fraz dla pętli
Sposób zapisu
|
Przykłady
|
Sprawdzenie warunku wewnątrz pętli
|
Ada[12][13]
|
Forth[14][15]
|
loop
-- instrukcje przed sprawdzeniem warunku
exit when warunek;
-- instrukcje po sprawdzeniu warunku
end loop;
-- instrukcje za pętlą
|
BEGIN
( instrukcje przed sprawdzeniem warunku )
( warunek ) WHILE
( instrukcje po sprawdzeniu warunku )
REPEAT
( instrukcje za pętlą )
|
Konstrukcje "zastępcze"
|
C[7][8][9][10], C++[9][11]
|
PL/I[5][6]
|
wymagane użycie
- instrukcji warunkowej
if , oraz
- instrukcji opuszczenia
break
|
wymagane użycie
|
while(1)
{
/* instrukcje przed sprawdzeniem warunku */
if(warunek) break;
/* instrukcje po sprawdzeniu warunku */
}
/* instrukcje za pętlą */
|
DO WHILE '1'B;
/* instrukcje przed sprawdzeniem warunku */
IF warunek THEN
GOTO LAB;
/* instrukcje po sprawdzeniu warunku */
END;
LAB: /* instrukcje za pętlą */
|
Typowe konstrukcje składniowe
Składnia poszczególnych języków programowania definiuje sposób zapisu poszczególnych elementów danego języka i jest różna w zależności od przyjętych przez jego autora rozwiązań. Spotyka się jednak w językach pewną grupę typowych, używanych słów kluczowych, które stanowią podstawę zapisu instrukcji[1][2][7][8][9] lub odpowiednich fraz instrukcji[5][6], definiujących warunki jej wykonania. Są to np.
- while warunek
- to słowo kluczowe stosowane w wielu językach programowania definiuje warunek, który musi być spełniony, aby pętla była wykonywana, stosowana jest zarówno na początku pętli (np. C[7][8][9], C++[9]:
while(warunek) instrukcja ; Pascal: while warunek do instrukcja ), jak i na końcu (np. C[7][8][9], C++[9]: do instrukcje while(warunek); ).
- until warunek
- to słowo kluczowe w różnych językach ma różne implikacje:
- warunek który określa, iż pętla będzie powtarzana dopóki warunek nie stanie się spełniony, np. Pascal:
reperat instrukcje until warunek ; Visual Basic[3], VBA[4]: Do Until warunek instrukcje Loop , Do instrukcje Loop Until warunek ;
- warunek, który jest sprawdzany na końcu pętli (choć zapis warunku znajduje się na jej początku w nagłówku definiującym), a pętla jest powtarzana jeżeli warunek jest spełniony, np. PL/I[5][6]:
DO UNTIL warunek; instrukcje END; (odpowiednik instrukcji do ... while(warunek); z języka C[7][8][9], C++[9]).
Przykłady pętli repetycyjnych
Przykłady pętli repetycyjnych
spełnienie/nie spełnienie
|
język programowania
|
miejsce sprawdzania warunku
|
miejsce zapisu warunku sprawdzanego na końcu pętli
|
na początku pętli
|
na końcu pętli
|
powtórzenie gdy warunek spełniony
|
C[7][8][9][10] C++[9][11]
|
while(a<MAX_A)
{
printf("a=%d",a++);
}
|
do
printf("a=%d",a++);
while(a<MAX_A);
|
na końcu
|
Pascal[1][2]
|
while a<MAX_A do
begin
writeln("a=",a);
a:=a+1
end;
|
|
|
Modula-2[16]
|
WHILE A<MAX_A DO
WRITE("a=",A);
A:=A+1
END;
|
|
|
PL/I[5][6]
|
DO WHILE A<MAX_A;
CALL WRITE('A=',A);
A=A+1;
END;
|
DO UNTIL A<MAX_A;
CALL WRITE('A=',A);
A=A+1;
END;
|
na początku
|
Visual Basic[3] VBA[4]
|
Do While a<MAX_A
Call WriteLine("a=", a)
a=a+1
Loop
|
Do
Call WriteLine("a=", a)
a=a+1
Loop While a<MAX_A
|
na końcu
|
powtórzenie gdy warunek nie spełniony
|
Do Until a=MAX_A
Call WriteLine("a=", a)
a=a+1
Loop
|
Do
Call WriteLine("a=", a)
a=a+1
Loop Until a=MAX_A
|
na końcu
|
Pascal[1][2] Modula-2[16]
|
|
repeat
writeln("a=",a);
a:=a+1
until a=MAX_A;
|
na końcu
|
Pętla repetycyjna w językach programowania
Uwagi
- ↑ Uwzględniono jedynie konstrukcje językowe zdefiniowane dla pętli; nie uwzględniono konstrukcji "zastępczych", tj. wymagających użycia instrukcji warunkowych.
- ↑ a b c d W językach takich jak Ada, Forth, czy PL/pgSQL, warunek sprawdzający wewnątrz pętli może zostać umieszczony na samym początku lub na samym końcu pętli, i wtedy mamy do czynienia z przypadkami krańcowymi, lecz nie są to odrębne konstrukcje składniowe, a jedynie przypadki szczególne sprawdzania warunku wewnątrz pętli, w związku z czym nie zostały one uwzględnione w zestawieniu
- ↑ Uwzględniono standardowo dostępną konstrukcję pętli; język Forth jest językiem rozszerzalnym – można w nim zdefiniować za pomocną odpowiednich kompilatorów (rozumianych w sensie języka Forth) nowe instrukcje sterujące i strukturalne, w tym konstrukcje pętli, które odpowiadałyby pozostałym przypadkom.
- ↑ a b W języku Perl warunki sprawdzane na początku pętli są strukturami sterującymi, warunki sprawdzane na końcu pętli są zrealizowane jako modyfikatory.
Przypisy
- ↑ a b c d e f g Michał Iglewski, Jan Madey, Stanisław Matwin: Pascal. Język wzorcowy – Pascal 360. Wyd. trzecie – zmienione. Warszawa: Wydawnictwa Naukowo-Techniczne, 1984, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-85060-53-7. ISSN 0867-6011. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h Andrzej Marciniak: Borland Pascal 7.0. Poznań: Nakom, 1994, seria: Biblioteka Użytkownika Mikrokomputerów. ISBN 83-85060-53-7. ISSN 0867-6011. (pol.). Brak numerów stron w książce
- ↑ a b c d e f Podręcznik Visual Basic na Wikibooks
- ↑ a b c d e f John Walkenbach: Excel 2003 PL. Programowanie w VBA.. HELION, 2004. ISBN 837361-504-0. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j Jan Bielecki: Rozszerzony PL/I i JCL w systemie OS/RIAD. Warszawa: Państwowe Wydawnictwo Naukowe, 1986, seria: Biblioteka Informatyki. ISBN 83-01-06146-4. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j M. I. Auguston i inni: Programowanie w języku PL/1 OS JS. Warszawa: Państwowe Wydawnictwo Naukowe, 1988. ISBN 83-01-07463-9. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j k l m n Brian W. Kernighan, Dennis M. Ritche: Język C. Warszawa: Wydawnictwa Naukowo-Techniczne, 1988, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-204-1067-3. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j k l m n Jan Bielecki: Turbo C z grafiką na IBM PC. Warszawa: Wydawnictwa Naukowo-Techniczne, 1990, seria: Mikrokomputery. ISBN 83-204-1101-7. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j k l m n o p q r s t u v w x y z Jan Bielecki: Od C do C++, programowanie obiektowe w języku C. Warszawa: Wydawnictwa Naukowo-Techniczne, 1990. ISBN 83-204-1332-X. (pol.). Brak numerów stron w książce
- ↑ a b c d e f g h i j Podręcznik języka C na Wikibooks
- ↑ a b c d e f g h i Podręcznik języka C++ na Wikibooks
- ↑ a b c A. Nico Habermann, Dewayne E. Perry: Ada dla zaawansowanych. Warszawa: Wydawnictwa Naukowo-Techniczne, 1989, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-204-1058-4. (pol.). Brak numerów stron w książce
- ↑ a b c Michał Morawski, Antoni M. Zajączkowski: Wstęp do programowania w języku Ada’95. Wyd. drugie. Łódź: 2004. [dostęp 2011-01-29]. (pol.). Brak numerów stron w książce
- ↑ a b c Jan Bielecki: Język FORTH. Warszawa: Wydawnictwa Naukowo-Techniczne, 1988, seria: Mikrokomputery. ISBN 83-204-0930-6. (pol.). Brak numerów stron w książce
- ↑ a b c Jan Ruszczyc: Poznajemy FORTH. Warszawa: SOETO, 1987, seria: Informatyka mikrokomputerowa. (pol.). Brak numerów stron w książce
- ↑ a b c d Niklaus Wirth: Modula 2. Warszawa: Wydawnictwa Naukowo-Techniczne, 1987, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-204-0828-8. ISSN 0867-6011. (pol.). Brak numerów stron w książce
- ↑ Tomasz Przechlewski: Opis języka AWK. [dostęp 2011-01-31]. (ang.). Brak numerów stron w książce
- ↑ Martin Richards: The BCPL Cintsys and Cintpos User Guide. Cambridge: Computer Laboratory University of Cambridge, January 28, 2011. [dostęp 2011-01-31]. (ang.). Brak numerów stron w książce
- ↑ Wojciech Rogowski, Arkadiusz Serodziński: Clipper 5.0. Warszawa: Wydawnictwo PLJ, 1991. ISBN 83-85190-20-1. (pol.). Brak numerów stron w książce
- ↑ Krzysztof Walczak: Język Clipper. Warszawa: Wydawnictwa Naukowo-Techniczne, 1990, 1991, seria: Podręczna Pamięć Programisty. ISBN 83-204-1359-11. (pol.). Brak numerów stron w książce
- ↑ Mike Ducka, tłumaczenie: Marcin Turski: Języki mikrokomputerów. Przewodnik dla początkujących. Basic, Pascal, Logo, Prolog, Comal, Forth. Warszawa: Wydawnictwa Naukowo-Techniczne, 1988. ISBN 83-204-0966-7. (pol.). Brak numerów stron w książce
- ↑ Bertrand Meyer: Eiffel*: A Language and Environment for Software Engineering. Goleta, California: Interactive Software Engineering Inc.. [dostęp 2011-01-31]. (ang.). Brak numerów stron w książce
- ↑ Martin Richards: The MCPL Programming Manual and User Guide. Cambridge: Computer Laboratory University of Cambridge, May 23, 2007. [dostęp 2011-01-31]. (ang.). Brak numerów stron w książce
- ↑ Podręcznik języka Perl na Wikibooks
- ↑ Jan Bielecki: PL/M język programowania mikroprocesorów. Wyd. drugie uzupełnione. Warszawa: Wydawnictwa Komunikacji i Łączności, 1987, seria: Elektronizacja. zeszyt 25. (pol.). Brak numerów stron w książce
- ↑ Jan Bielecki: System operacyjny ISIS-II. Warszawa: Wydawnictwa Naukowo-Techniczne, 1987, seria: Mikrokomputery. ISBN 83-204-0893-8. (pol.). Brak numerów stron w książce
- ↑ PostgreSQL 8.3.13 Documentation. [dostęp 2011-01-31]. (ang.). Brak numerów stron w książce
- ↑ Podręcznik języka Ruby na Wikibooks
Bibliografia
- Michael Marcotty, Henry Ledgord, tłumaczenie: Krystyna Jerzykiewicz: W kręgu języków programowania. Warszawa: Wydawnictwa Naukowo-Techniczne, 1980, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-204-1342-7. (pol.). Brak numerów stron w książce
- John E. Nicholls: Struktura języków programowania. Warszawa: Wydawnictwa Naukowo-Techniczne, 1980, seria: Informatyka. ISBN 83-204-0246-8. (pol.). Brak numerów stron w książce
- Mike Ducka, tłumaczenie: Marcin Turski: Języki mikrokomputerów. Przewodnik dla początkująych. Basic, Pascal, Logo, Prolog, Comal, Forth. Warszawa: Wydawnictwa Naukowo-Techniczne, 1988. ISBN 83-204-0966-7. (pol.). Brak numerów stron w książce
|
|