Pętla ogólna to konstrukcja programistyczna stanowiąca jeden z rodzajów pętli, dostępna w niektórych językach programowania. Pętla ta umożliwia między innymi definiowanie pętli iteracyjnych. Jednak składnia tego rodzaju pętli zdefiniowana jest na niższym poziomie abstrakcji od pętli iteracyjnych, co oznacza, iż programista, który definiuje w kodzie źródłowym określony algorytm z użyciem takiej pętli, musi jawnie, wprost, definiować warunek zakończenia takiej pętli oraz jawnie modyfikować wartość zmiennej sterującej (o ile występuje). Pętle tego typu dostępne są w grupie języków określanych w literaturze przedmiotu jako rodzina języka C oraz języków C-podobnych (także: C-pochodnych). Obejmuje ona między innymi takie języki jak: C[1][2][3][4], C++[3][5], C#, Java, JavaScript[6], D[7], C--, i inne, a także języki których składnia była przez autorów tych języków choć częściowo wzorowana na składni języka C, np. Perl[8].

Składnia

edytuj

Pętla ta w językach programowania definiowana jest za pomocą słowa kluczowego for. Po nim, w nawiasach okrągłych, definiowane są warunki wykonania taj pętli, w trzech sekcjach rozdzielonych znakami średnika. Po tak skonstruowanym nagłówku pętli umieszcza się instrukcję, która stanowi iterację i podlegać będzie wielokrotnemu wykonaniu w ramach pętli. Jeżeli iterowaniu ma podlegać większa ilość instrukcji, w miejsce pojedynczej instrukcji, stosuje się instrukcję blokową.

Składnia w języku C[1][2][3][4], typowa także dla wielu innych języków programowania:

for(inicjalizacja; warunek-zakończenia; zmiana-wartości)
 {
   /* instrukcje */
 }

Działanie pętli

edytuj
 
Diagram pętli for typu C

Działanie tej pętli ma następujący przebieg:

  1. wykonaj instrukcję zawartą w sekcji inicjalizacyjnej (pozycja A na schemacie)
  2. sprawdź warunek (pozycja B na schemacie)
    • jeżeli nie jest spełniony (flase – fałsz – 0), to zakończ wykonywanie pętli (gałąź FALSE na schemacie)
    • jeżeli jest spełniony (true - prawda – wartość inna niż 0), to przejdź do wykonania kolejnej iteracji (gałąź TRUE na schemacie)
  3. wykonaj iterację (pozycja D na schemacie)
  4. wykonaj zmianę wartości (pozycja C na schemacie)
  5. wróć do punktu 2 (nieoznaczona gałąź na schemacie).

Należy podkreślić, że powyższy opis dla sekcji A: inicjalizacja; B: warunek-zakończenia; C: zmiana-wartości; jest tylko symbolicznym określeniem celu stworzenia tych sekcji w definicji pętli i nie ma żadnego ograniczenia wobec możliwości zapisania tam wyrażeń nie związanych z działaniem pętli, np. w sekcji A, choć ze względu na czytelność kodu źródłowego nie jest to zalecane jako zaciemnianie kodu. Ponadto w sekcji B: warunek-zakończenia; wyrażenie zawarte w tej części definicji pętli musi zwrócić wartość logiczną, która określi czy pętla ma zostać powtórzona czy zakończona. W językach takich jak C[1][2][3][4], C++[3][5], w których nie wprowadzono wprost logicznego typu danych stosuje się odpowiednią interpretację wartości należących do typów całkowitoliczbowych, tzn. wartość równa zero interpretowana jest jako wartość logiczna fałsz (false), inne wartości różne od zera jako wartość logiczna prawda (true). Jeżeli natomiast w sekcji B nie zapisano jakiegokolwiek warunku zakończenia pętli, to przyjmuje się, że warunek jest spełniony (prawda - true) i pętla będzie pętlą nieskończoną.

Na uwagę zasługuje fakt, iż w sekcji A: inicjalizacja, można także zawierać deklarację zmiennych lokalnych. Definicja konkretnego języka programowania, bądź jego implementacja, określa, czy zmienna tu zadeklarowana jest widoczna tylko w ramach wykonywanej pętli, czy także po jej zakończeniu, w bloku obejmującym daną pętlę.

Pętla ogólna w językach programowania

edytuj

Jak wyżej zaznaczono, pętla tego rodzaju dostępna jest w zasadzie w niezmienionej postaci w wielu językach, których składnia choć częściowo wzorowana jest na języku C. W niektórych językach pętla ta została rozszerzona w stosunku do pierwowzoru o możliwość definiowana pętli po kolekcji lub innym agregacie danych, czyli pętle typu foreach, np. Perl[8].

Pętla ogólna w językach programowania
język programowania składnia
Alef[9] for(A;B;C) D
C[1][2][3][4] for(A;B;C) D
C++[3][5] for(A;B;C) D
C++/CLI for(A;B;C) D
C-- for(A;B;C) D
C# for(A;B;C) D
D[7] for(A;B;C) D
Go for A; B; C { D }
Java for(A;B;C) D
JavaScript[6] for(A;B;C) D
Objective-C for(A;B;C) D
Perl[8] for(A;B;C) { D }
PHP[10] for(A;B;C) { D }
SAC[11] for(A;B;C) D
Uwaga: oznaczenia A,B,C,D odnoszą się do oznaczeń użytych na diagramie.

Porównanie z innymi konstrukcjami

edytuj

Pętla ogólna, jako pętla stanowiąca pewne uogólnienie na niższym poziomie abstrakcji od innych pętli, może realizować także funkcje pewnych innych pętli. Można także zrealizować czynności pętli ogólnej za pomocą innych konstrukcji dostępnych w danym języku programowania. Jedynym ograniczeniem jest zasada, że w tej pętli warunek jej zakończenia, bądź powtórzenia pętli sprawdzany jest na jej początku. Nie można więc zrealizować pętli, w której warunek sprawdzany jest na końcu, co skutkuje tym, że pętla taka byłaby wykonana zawsze co najmniej jeden raz.

Porównanie z pętlą nieskończoną

edytuj
Pętla ogólna – pętla nieskończona
pętla ogólna (język C)[1][2][3][4] w innym przykładowym języku, w którym nie ma pętli ogólnej
przykład pętla repetycyjna realizacja pętli za pomocą
instrukcji warunkowej i skoku
język programowania przykład
for(;;)
 {
   /* instrukcje */;
 }
while(1)
 {
   /* instrukcje */;
 }
start:
   /* instrukcje */;
goto start;
Ada[12][13]
loop
   -- instrukcje
end loop

Implementacja pętli nieskończonej za pomocą pętli ogólnej jest bardzo prosta – polega zwyczajnie na pominięciu warunku zakończenia pętli, co równoznaczne jest z przyjęciem, iż warunek ten jest zawsze spełniony. Realizacja tej samej pętli za pomocą instrukcji repetycyjnej wymaga zapisania wprost warunku zawsze spełnionego. Jednak w przeciwieństwie do pętli nieskończonych (przykład w języku Ada[12][13]), w przypadku pętli ogólnej nadal wymagany jest zapis poszczególnych sekcji (choć pustych) ograniczonych nawiasami i średnikami.

Porównanie z pętlą repetycyjną

edytuj
Pętla ogólna – pętla repetycyjna
pętla ogólna (język C)[1][2][3][4] w innym przykładowym języku, w którym nie ma pętli ogólnej
przykład pętla repetycyjna realizacja pętli za pomocą
instrukcji warunkowej i skoku
język programowania przykład
for(;a<b;)
 {
   /* instrukcje */;
 }
while(a<b)
 {
   /* instrukcje */;
 }
start: if(!(a<b))
 goto koniec;
else
 {
   /* instrukcje */;
 }
goto start;
koniec:
Pascal[14][15]
while a<b do
 begin
   -- instrukcje
 end;

Implementacja pętli repetycyjnej za pomocą pętli ogólnej jest bardzo prosta, odpowiedni warunek zapisuje się analogicznie jak dla pętli repetycyjnej. Jedynym ograniczeniem jest to, że warunek zawsze sprawdzany jest na początku pętli i brak jest możliwości realizacji pętli ze sprawdzaniem warunku na końcu pętli (np. konstrukcja do ... while(warunek); z języka C[1][2][3][4] i pochodnych).

Porównanie z pętlą iteracyjną

edytuj
Pętla ogólna – pętla iteracyjna
pętla ogólna (język C)[1][2][3][4] w innym przykładowym języku, w którym nie ma pętli ogólnej
przykład pętla repetycyjna realizacja pętli za pomocą
instrukcji warunkowej i skoku
język programowania przykład
for(i=1;i<MAX;i++)
 {
   /* instrukcje */;
 }
i=1;
while(i<MAX)
 {
   /* instrukcje */;
   i++;
 }
start: if(!(i<MAX))
 goto koniec;
else
 {
   /* instrukcje */;
   i++;
 }
goto start;
koniec:
Modula-2[16]
FOR i:=1 TO MAX-1 DO
  (* instrukcje *)
END

Pętla ogólna daje możliwość w pełni implementacji pętli iteracyjnych. W sekcji pierwszej zapisuje się wyrażenie inicjujące zmienną sterującą, analogicznie jak przy zapisach stosowanych w pętlach iteracyjnych. W kolejnych sekcjach definiujących działanie pętli ogólnej ujawnia się jednak jej niższy poziom abstrakcji: programista musi wprost, jawnie definiować warunek zakończenia pętli oraz odpowiedzią zmianę wartości zmiennej sterującej. Taka konstrukcja może jednak stanowić zaletę: daje większe i bardziej elastyczne możliwości konstruowania pętli, w tym także pętli złożonych (patrz następny przykład), dowolna wielkość kroku zmiennej sterującej i jej typu.

Porównanie z pętlą złożoną

edytuj
Pętla ogólna – pętla złożona
pętla ogólna (język C)[1][2][3][4] w innym przykładowym języku, w którym nie ma pętli ogólnej
przykład pętla repetycyjna realizacja pętli za pomocą
instrukcji warunkowej i skoku
język programowania przykład
for(i=1;(i<MAX)&&(a<b);i++)
 {
   /* instrukcje */;
 }
i=1;
while((i<MAX)&&(a<b))
 {
   /* instrukcje */;
   i++;
 }
start: if(!((i<MAX)&&(a<b)))
 goto koniec;
else
 {
   /* instrukcje */;
   i++;
 }
goto start;
koniec:
PL/I[17][18]
DO I=1 TO MAX-1 WHILE A<B;
  /* instrukcje  */
END;
Turbo Pascal[15]
for i:=1 to MAX-1 do
 begin
   if not (a<b) then break;
  /* instrukcje  */
 end;

Pętle umożliwiające złożone definiowanie warunków przebiegu realizacji, w tym łączenia iteracji z warunkami pętli repetycyjnych, rzadziej występują w językach programowania. Przykładowe języki programowania to PL/I[17][18] czy Algol 68[19]. Brak tych mechanizmów zmusza w innych językach (np. Pascal[14][15]), do stosowania instrukcji warunkowych i skoku (lub jej substytutu jakim jest instrukcja opuszczenia). Pętla ogólna jest tak skonstruowana, że daje możliwość realizacji części możliwości zawartych w pętlach złożonych, tzn. realizacji iteracji w połączeniu z warunkami pętli repetycyjnych sprawdzanych na początku pętli (ale nie w pełni, gdyż nie daje możliwości kontynuowania wykonywania pętli dla nowych warunków, oraz sprawdzania warunków na końcu pętli – np. pętla złożona w PL/I[17][18]), bez uciekania się do instrukcji warunkowych i skoku.

Przypisy

edytuj
  1. a b c d e f g h i 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.).
  2. a b c d e f g h i Jan Bielecki: Turbo C z grafiką na IBM PC. Warszawa: Wydawnictwa Naukowo-Techniczne, 1990, seria: Mikrokomputery. ISBN 83-204-1101-7. (pol.).
  3. a b c d e f g h i j k l Jan Bielecki: Od C do C++, programowanie obiektowe w języku C. Warszawa: Wydawnictwa Naukowo-Techniczne, 1990. ISBN 83-204-1332-X. (pol.).
  4. a b c d e f g h i Podręcznik języka C na Wikibooks
  5. a b c Podręcznik języka C++ na Wikibooks
  6. a b Wojciech Romowicz: HTML i JavaScript. HELION, 1998. ISBN 83-7197-046-3. (pol.).
  7. a b Podręcznik języka D na Wikibooks
  8. a b c Podręcznik języka Perl na Wikibooks
  9. Phil Winterbottom: Alef Language Reference Manual. doc.cat-v.org. (ang.).
  10. Podręcznik języka PHP na Wikibooks
  11. Sven-Bodo Scholz, Stephan Herhut, Frank Penczek, Clemens Grelck: SaC 1.0 Single Assignment C Tutorial. University of Hertfordshire School of Computer Science, University of Amsterdam Institute of Informatics, December 2010, s. 56. (ang.).
  12. a b 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.).
  13. a b 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.).
  14. a b Michał Iglewski, Jan Madey, Stanisław Matwin: Pascal. Język wzorcowy – Pascal 360. Wyd. wydanie trzecie – zmienione. Warszawa: Wydawnictwa Naukowo-Techniczne, 1984, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-85060-53-7. ISSN 0867-6011. (pol.).
  15. a b c Andrzej Marciniak: Borland Pascal 7.0. Poznań: Nakom, 1994, seria: Biblioteka Użytkownika Mikrokomputerów. ISBN 83-85060-53-7. ISSN 0867-6011. (pol.).
  16. Niklaus Wirth: Modula 2. Warszawa: Wydawnictwa Naukowo-Techniczne, 1987, seria: Biblioteka Inżynierii Oprogramowania. ISBN 83-204-0828-8. ISSN 0867-6011. (pol.).
  17. a b c 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.).
  18. a b c 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.).
  19. Jan Małuszyński, Krzysztof Pisecki, A. van Wijngaarden, B.J. Mailloux, J.E.L. Peck, C.H.A. Koster, M. Sintzoff, .H. Lindsey, L.G.L.T. Meertens, R.G. Fisker, w tłumaczeniu Jana Małuszyńskiego i Krzysztofa Piseckiego: Algol 68. Wprowadzenie do języka Algol 68. Zmieniony raport o języku algorytmicznym Algol 68. Warszawa: Wydawnictwa Naukowo-Techniczne, 1980, seria: Informatyka. ISBN 83-204-0161-5. (pol.).

Bibliografia

edytuj
  • 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.).
  • John E. Nicholls: Struktura języków programowania. Warszawa: Wydawnictwa Naukowo-Techniczne, 1980, seria: Informatyka. ISBN 83-204-0246-8. (pol.).