Strona główna » C++ » Kurs » Pętla For
 

Pętla For

Wstęp

W trakcie wykonywania programu może zaistnieć potrzeba powtórzenie tego samego zestawu określoną ilość razy. W przypadku, gdy chcemy powtórzyć coś dwa lub trzy razy to kod pozostaje prosty. Problem zaczyna się kiedy chcemy np. wypisać 1000 elementów. W C++ do powtarzania tej samej instrukcji możemy zastosować pętle for. Jej składnia jest następująca:

  1. for ( [inicjalizacja]; [warunek]; [polecenie_po_pętli] ) {
  2.  [ciąg_instrukcji]
  3. }

Program rozpoczynają pętle wykonuje najpierw inicjalizacja. Następnie o ile jest spełniony warunek to wykonuje ciąg instrukcji. Na zakończenie iteracji, czyli jednej pełnej pętli wykonywane jest polecenie po pętli.

Wykorzystanie funkcji

Instrukcja for pozwala zapisać program w bardzo elegancki sposób. Zazwyczaj jako inicjalizacja deklaruje się jakąś zmienną, a na koniec pętli zwiększa się wartość o 1. Przykładowym wykorzystaniem jest wypisanie na ekran liczb od 1 do 100:

  1.   for (int i = 1; i <= 100; i++) {
  2.     cout << i << " ";
  3.   }

W tym przypadku program początkowo (1.) przypisze zmiennej i wartość 1. Następnie sprawdzi warunek. (2.) Wykona instrukcje i (1.) zwiększy wartość zmiennej i o 1. Potem ponownie sprawdzi warunek, wykona ciąg instrukcji itd. Jednak kiedy skończymy ciag instrukcji kiedy i = 100 to po dodaniu 1 otrzymamy 101. Wtedy warunek nie zostanie spełniony. Program wtedy przejdzie do instrukcji w linijce (4.).

Odpowiednio zmieniając wartości zmiennej i możemy otrzymywać inne wyniki. Jeśli zaczniemy zwiększać wartość i o dwa, a nie jeden to na ekran zostaną wypisane wszystkie liczby nieparzyste z zakresu od 1 do 100:

  1.   for (int i = 1; i <= 100; i += 2) {
  2.     cout << i << " ";
  3.   }

Oczywiście nazwa zmiennej i jest dowolna. W moim przypadku używam jej zawsze. Nazwa i to pierwsza litera słowa iteracja (czy angielskiego index).

Przeciwko for

Istnieje możliwość zostawienia niektórych pól pętli for puste. Wtedy w każdym przypadku program inaczej się zachowa.

Bez Pola inicjalizującego

  1.   int i = 1;
  2.   for ( ; i <= 100; i += 2 ) {
  3.     cout << i << " ";
  4.   }

W takim przypadku nie zostanie wykonana żadna instrukcja przed rozpoczęciem pierwszej pętli. Jeśli jak w powyższym kodzie chcemy wykorzystać zmienną i to należy ją zadeklarować przed pętlą for.

Bez Ciągu instrukcji

  1.   for (int i = 1; i <= 100; i += 2 ) { }

Tego typu zapis jest poprawny, ale ciężko znaleźć dla niego zastosowanie. Taki kod zużyje tylko zasoby komputera. Program wykona odpowiednią ilość pętli i na początku zadeklaruje zmienną i, ale nic poza tym. Jest to fragment kodu, który nigdy nie powinien pojawić się w programie. Istnieją sytuacje kiedy chcemy spowolnić wykonywanie programu, ale istnieją do tego inne funkcje.

Bez Instrukcji po pętli

  1.   for (int i = 1; i <= 100;) {
  2.     cout << i << " ";
  3.   }

Kolejny poprawny zapis... ale czy na pewno ? Przypuśćmy, że uruchomimy taki program. W pierwszej pętli zostanie wypisane jeden, w drugiej jeden, ... w tysięcznej pętli jeden! Powstała nam tutaj pętla nieskończona, która nigdy się nie skończy, ponieważ warunek zawsze będzie spełniony (i zawsze równa się jeden). Istnieje możliwość, aby pole instrukcji po pętli było puste, ale należy wtedy pamiętać, że przykładową zmianę wartości i należy wywołać w pętli po bloku instrukcji.

Bez Warunku

  1.   for (int i = 1; ; i += 2) {
  2.     cout << i << " ";
  3.   }

Program teoretycznie dobrze działa. Wypisuje kolejne nieparzyste wartości jednak pętla znów jest nieskończona. Jest spowodowana faktem, że pusty warunek jest traktowany przez program jako wartość prawda. Innymi słowy nie istnieje warunek, który może nie być spełniony. Tego typu pętle również nie powinny istnieć w programie.

Pętle zagnieżdżone

Załóżmy, że chcemy wypisać na ekran 100 literek o, które będą zapisane w kwadracie 10x10. W tym celu warto użyć pętli for w pętli for:

  1.   for (int i = 0; i < 10; i++){
  2.     for (int j = 0; j < 10; j++){
  3.       cout << "o";
  4.     }
  5.     cout << "\n";
  6.   }

(1.) Rozpoczynamy wypisywania 10 wierszy w którym (2.) wypisujemy 10 razy (3.) literę o. Na koniec każdej pętli nadrzędnej (tj. końca wiersza) (5.) dopisujemy znak nowej linii. Po uruchomieniu i kompilacji faktycznie uzyskamy coś na kształt kwadratu (chociaż ze względu na konsolowe wyświetlanie wynikiem jest prostokąt):

  1. oooooooooo
  2. oooooooooo
  3. oooooooooo
  4. oooooooooo
  5. oooooooooo
  6. oooooooooo
  7. oooooooooo
  8. oooooooooo
  9. oooooooooo
  10. oooooooooo

Pułapki zmiennych

Niepoprawnie jest założyć, że w pętli zagnieżdżonej możemy użyć zmiennej o tej samej nazwie. Owszem program wtedy się skompiluje, ale rezultaty na ekranie mogą być inne niż byśmy chcieli. Przykładowo warto przyjrzeć się poniższemu kodu:

  1.   for (int i = 0; i < 10; i++){
  2.     for (i = 0; i < 10; i++){
  3.       cout << "o";
  4.     }
  5.     cout << "\n";
  6.   }

Pokazany kod rozpoczyna działanie i (1.) ustawia zmienną i na 0. Następnie (2.) podczas rozpoczęcia drugiej pętli zmienna i ponownie jest ustawiona na 0 i jest zwiększana o 1, aż i = 10. Wtedy wewnętrzna pętla kończy się program przechodzi do (5.) następnej instrukcji. Niestety wypisana zostanie tylko pierwsza linijka, ponieważ i nie spełnia warunku pierwszej pętli for.

Wspomniany przypadek zakończy działanie, ale w przypadku, gdy i spełniałoby zawsze warunek pierwszej pętli to napisany kod będzie nieskończony tak jak poniżej:

  1.   for (int i = 0; i < 10; i++){
  2.     for (i = 0; i < 5; i++){
  3.       cout << "o";
  4.     }
  5.     cout << "\n";
  6.   }

Podsumowanie

Lekcja 8 dobiegła końca. Zajrzyj do kodu źródłowego, aby przeanalizować wypisywanie danych jeszcze raz. Następnie spróbuj wykonać zadania, aby utrwalić materiał.

Zadania

Zadanie 1

Napisz program, który wypisze na ekran pierwsze 100 liczb parzystych.

Zadanie 2

Napisz program, który wypisze liczby podzielne przez 16 z zakresu od 1 do 100.

* Zadanie 3

Napisz program, który wypisze na ekran tabliczkę mnożenia.