. Pętle for Przykłady.1. Bez użycia pętli while ani rekurencji, napisz program, który wypisze na ekran kolejne liczby naturalne od 0 do pewnego danego n. 5 int n; 6 cin >> n; 8 for (int i = 0; i <= n; i = i+1) { 9 cout << i << endl; 10 } 11 12 return 0; 1 } Wiele pętli, które będziemy chcieli napisać, zawiera w sobie trzy elementy: inicjalizację, warunek i krok pętli. Żaden z tych elementów nie jest wymagany, jednak z reguły w pętli pojawią się wszystkie. W poprzednim rozdziale nauczyliśmy się wykorzystywać pętle while, w których jedynie warunek jest elementem stałym. Inicjalizacja i krok pętli umieszczaliśmy poza właściwą konstrukcją pętli, w trzech różnych miejscach. Dotyczą one jednak tego samego: zachowania iteratora, dlaczego więc rozrzucać je po całym programie? Pętle for pozwalają nam zebrać te trzy elementy w jedno miejsce. Ich konstrukcja wygląda następująco: najpierw słowo kluczowe for, następnie w nawiasach okrągłych, oddzielone średnikami, kolejno: inicjalizacja, warunek i krok pętli. W końcu w nawiasach klamrowych, jak zwykle, umieszczamy fragment kodu, który chcemy wielokrotnie wykonać. W liniach 8-10 powyższego programu widzimy przykład takiej właśnie pętli. Najpierw słowo for, następnie definicja i przypisanie wartości zmiennej i, która pełni funkcję iteratora. Potem, po średniku, warunek, a następnie, po kolejnym średniku, zwiększamy wartość iteratora. 50
W porównaniu do przykładu 6.2, program ten nie zawiera niemal żadnego nowego kodu. Zmienia się jedynie położenie elementów pętli, a słowo while zastępujemy słowem for. Cały program zachowuje się przy tym identycznie do programu z przykładu 6.2. Uwaga! Wykonanie pętli for ma następujący przebieg: najpierw wykonywana jest inicjalizacja, następnie sprawdzany jest warunek. Jeżeli warunek jest spełniony, to wykonujemy najpierw ciało pętli (czyli fragment kodu w klamerkach), a następnie krok pętli i wracamy do sprawdzania warunku. A więc: inicjalizacja wykonywana jest tylko raz, przed pierwszym sprawdzeniem warunku. Warunek jest sprawdzany przed każdym wykonaniem pętli, a krok po każdym wykonaniu pętli..2. Napisz program, który pobierze od użytkownika n liczb, a następnie wypisze na ekran ich sumę. 5 int n; 6 cin >> n; 8 int suma = 0; 9 for (int i = 0; i < n; i = i+1) { 10 int k; 11 cin >> k; 12 1 suma = suma + k; 15 16 cout << suma << endl; 1 return 0; 18 } W tym zadaniu widzimy znany już schemat pobierz n liczb, jednak przy użyciu pętli for. Zaczynamy od pobrania liczby n w liniach 5-6. Następnie w pętli w liniach 9-14 n razy pobieramy liczbę i dodajemy jej wartość do akumulatora suma. Znów, w porównaniu do przykładu 6.6, powyższy program nie zawiera żadnego nowego kodu, a jedynie zmienia układ kodu już istniejącego (no i słowo while zastępuje słowem for). 51
.. Napisz program, który będzie pobierać od użytkownika liczby aż do napotkania 0, a następnie wypisze na ekran ile liczb pobrał. 5 int ile; 6 int n = 1; 8 for (ile = 0; n!= 0; ile = ile+1) { 9 cin >> n; 10 } 11 12 cout << ile << endl; 1 return 0; Znów mamy do czynienia z przepisaniem przykładu z poprzedniego rozdziału (tym razem przykład 6.4) przy użyciu pętli for. Nie wymaga on raczej większego komentarza, z wyjątkiem zmiennej ile, która tworzona jest przed pętlą (w linii 5), zamiast wewnątrz inicjalizacji (linia 8). Dzieje się tak dlatego, że zmienne tworzone wewnątrz pętli, w tym wewnątrz inicjalizacji, istnieją jedynie wewnątrz pętli. Po zakończeniu jej działania, zmienne te nie są już dla nas dostępne. W tym programie jednak interesuje nas wypisanie wartości zmiennej ile po zakończeniu działania pętli, stąd musimy stworzyć ją przed rozpoczęciem pętli. Uwaga! W tym przykładzie tworzymy zmienną poza pętlą, a w inicjalizacji przypisujemy jej jedynie początkową wartość. Jest jednak dopuszczalne całkowite pominięcie inicjalizacji, na przykład: 1 int ile = 0; 2 int n = 1; 4 for (; n!= 0; ile = ile+1) { 5 cin >> n; 6 } Jest to jedyna różnica w działaniu między pętlą while, a pętlą for. Jest to zdecydowanie pożądane zachowanie, jako że zmienne powinny istnieć wyłącznie 52
tak długo, jak są potrzebne. Stąd tworzymy je tak późno jak się da. Od teraz możemy również pozbywać się ich tak szybko, jak to tylko możliwe. Uwaga! Znamy teraz dwie, niemal równoważne, metody wielokrotnego wykonywania tego samego fragmentu kodu. Której z nich należy używać? W języku C++ najczęściej stosować będziemy pętlę for, chyba że istnieją powody, aby użyć pętli while. Takim powodem może być na przykład skomplikowana inicjalizacja i krok pętli, których nie chcemy (lub nie możemy) umieszczać w jednej linii..4. Napisz program, który wypisze na ekran k kolejnych potęg 2, zaczynając od 2 0, gdzie k jest dane przez użytkownika. 5 int k; 6 cin >> k; 8 for (int i = 0, n = 1; i < k; i = i+1) { 9 cout << n << endl; 10 n = n*2; 11 } 12 1 return 0; Ponownie, przykład ten jest kopią przykładu 6.5. Jedna rzecz warta uwagi to stworzenie więcej niż jednej zmiennej w inicjalizacji (linia 8). Możemy stworzyć wiele zmiennych jednego i każdej z nich przypisać inną wartość, oddzielając je przecinkami. Istotne jest to, że typ podajemy tylko raz, przed pierwszą ze zmiennych. Pytania.1. Porównaj programy z przykładów 6.2 i.1. Zwróć uwagę na podobieństwa i różnice między nimi. Czy w którymś z przykładów znajduje się kod, którego nie ma w drugim z nich?.2. Dokonaj podobnego porównania dla pozostałych programów z tego i odpowiednich przykładów z poprzedniego rozdziału. 5
.. Który z dwóch poniższych fragmentów kodu skompiluje się? Jeżeli któryś z nich spowoduje błąd kompilacji jaki i dlaczego? Jeżeli oba się kompilują, jaka jest różnica w ich działaniu? 1 // Fragment 1 2 int n = 10; int i = 0; 4 int suma = 0; 5 while (i < n) { 6 suma = suma + i; i = i + 1; 8 } 9 cout << i << " " << suma; 10 11 // Fragment 2 12 int n = 10; 1 int suma = 0; 14 for (int i = 0; i < 10; i = i+1) { 15 suma = suma + i; 16 } 1 cout << i << " " << suma;.4. Co wypisze poniższy fragment kodu? Dlaczego zmienna n tworzona jest tutaj przed pętlą, a nie w inicjalizacji? 1 int n; 2 for (n = 0; n < 10; n = n+1) { } cout << n << endl;.5. Co wypisze poniższy fragment kodu? 1 int n = 10; 2 for (n = 0; 1 < 0; n = n+1) { cout << n << endl; 4 } 5 cout << n << endl; Zadania Rozwiąż zadania z poprzedniego rozdziału, tym razem używając pętli for. 54