Podstawy
programowania
Ćwiczenie laboratoryjne:
Instrukcje obliczeń cyklicznych. Pętla for, while, do..while()
autor: dr inż. Michał Łabowski
▪ michal.labowski@wat.edu.pl
▪ www.mlabowski.wel.wat.edu.pl
Pętle w C++
2
W języku C i C++ występują trzy rodzaje pętli:
• for (czytaj: dla)
• while (czytaj: dopóki lub tak długo jak)
• do while (czytaj: rób… dopóki) Pętla for:
• stosowana wtedy, gdy dokładnie wiadomo ile razy pętla ma się wykonać,
• najbardziej odporna na przypadkowe błędy programisty Składnia:
for (instrukcja_inicjujaca; wyrazenie_warunkowe; instrukcja_kroku) {
instrukcje;
}
instrukcja_inicjujaca – najczęściej operacja przypisania początkowej wartości iteratorowi, np. int i = 0. Obiekt zdefiniowany w instrukcji inicjującej istnieje tylko w ramach pętli for (to zmienna automatyczna o zasięgu blokowym).
wyrazenie_warunkowe – pętla (czyli instrukcje zawarte pomiędzy klamrami) wykonuje się tak długo, jak wyrażenie to ma wartość true, np. i < 10
instrukcja_kroku – instrukcja powodująca zmianę wartości iteratora, np. ++i Te trzy elementy muszą być rozdzielone średnikami ;
Składnia nieskończonej pętli for: for(;;);
for
3
Przykład 1. Napisz program, który za pomocą pętli for dla danych wartości x zmieniających się od 0 do 10 wyznaczy wartość funkcji y = 3x.
for
4
Przykład 1. Napisz program, który za pomocą pętli for dla danych wartości x zmieniających się od 0 do 10 wyznaczy wartość funkcji y = 3x.
Nr linii Opis
9-13 Pęta for. Pierwszy obieg pętli jest szczególny, ponieważ na jego początku wykonywana jest instrukcja inicjująca. Dalszy przebieg jest już standardowy: wykonywane jest sprawdzenie wyrażenia warunkowego, jeśli jest ono spełnione wykonują się instrukcje (linie 11, 12), a na koniec instrukcja kroku. Kolejne obiegi pętli rozpoczynają się od sprawdzenia warunku, następnie mogą być wykonane instrukcje i krok.
while
5
Pętla while:
• stosowana wtedy, gdy nie wiadomo z góry ile razy pętla ma się wykonać (np.
liczbę tę wprowadza użytkownik programu)
• podatna na błędy programisty, ponieważ instrukcja_inicjujaca, wyrazenie_warunkowe oraz instrukcja_kroku nie znajdują się w jednej linii, więc łatwo o którejś z nich zapomnieć.
Składnia:
instrukcja_inicjujaca;
while (wyrazenie_warunkowe) {
instrukcje;
instrukcja_kroku;
}
Cechą charakterystyczną pętli while jest to, że instrukcje mogą nigdy się nie wykonać, jeśli wyrazenie_warunkowema początkowo wartość false.
Składnia nieskończonej pętli while:
while(true) {
instrukcje;
}
while
6
Przykład 2. Napisz program, który za pomocą pętli while dla danych wartości x zmieniających się od 0 do 10 wyznaczy wartość funkcji y = 3x.
Nr linii Opis
9 instrukcja inicjująca
10-15 Pętla while. Na początku pętli sprawdzane jest wyrażenie warunkowe (linia 10), jeśli jest ono spełnione wykonują się instrukcje z linii 12-14, gdzie linia 14 to instrukcja kroku.
do while
7
Pętla do while:
• stosowana wtedy, gdy nie wiadomo z góry ile razy pętla ma się wykonać (np.
liczbę tę wprowadza użytkownik programu) – podobnie jak pętla while,
• podatna na błędy programisty, ponieważ instrukcja_inicjujaca, wyrazenie_warunkowe oraz instrukcja_kroku nie znajdują się w jednej linii, więc łatwo o którejś z nich zapomnieć – podobnie jak pętla while,
Składnia:
instrukcja_inicjujaca;
do {
instrukcje;
instrukcja_kroku;
} while (wyrazenie_warunkowe);
Cechą charakterystyczną pętli while jest to, że instrukcje muszą się wykonać co najmniej raz, nawet jeśli wyrazenie_warunkowe ma początkowo wartość false.
Sprawdzenie warunku znajduje się bowiem po instrukcjach (w pętli while – przed).
Składnia nieskończonej pętli do while:
do {
instrukcje;
} while(true);
do while
8
Przykład 3. Napisz program, który za pomocą pętli do while dla danych wartości x zmieniających się od 0 do 10 wyznaczy wartość funkcji y = 3x.
Nr linii Opis
9 instrukcja inicjująca
10-15 Pętla do while. Po wejściu do pętli najpierw wykonywane są instrukcje z linii 12-14, a dopiero później sprawdzane jest wyrażenie warunkowe (linia 15),
14 instrukcja kroku.
break
9
Instrukcja break powoduje natychmiastowe przerwanie wykonywania pętli for, while, do while, jak również poznanej wcześniej instrukcji switch [1]. W przypadku pętli zagnieżdżonych break powoduje przerwanie pętli, w której zostało wywołane.
Przykład 4. Zmodyfikuj program z przykładu 1, tak aby wyznaczanie i wyświetlanie wartości zatrzymało się dla x równego 4. Wykorzystaj instrukcję break.
break
10
Nr linii Opis
12 sprawdzenie warunku, czy x jest równy 4
14 jeśli warunek z linii 12 jest spełniony, wówczas wykonywana jest instrukcja break, za sprawą której następuje wyjście z pętli for i przejście do następującej po niej linii kodu, czyli linii nr 17.
continue
11
Instrukcja continue powoduje zaniechanie wykonywania dalszej części instrukcji w pętli – przerywany jest aktualny obieg pętli, następuje wykonanie instrukcji kroku i sprawdzenie warunku, a jeśli jest on spełniony pętla wykonuje się dalej.
Przykład 5. Zmodyfikuj program z przykładu 1, tak aby nie wyświetlono wyników dla x równego 4. Wykorzystaj instrukcję continue.
continue
12
Nr linii Opis
11 sprawdzenie warunku, czy x jest równy 4
13 jeśli warunek z linii 11 jest spełniony, wówczas wykonywana jest instrukcja continue, za sprawą której następuje przerwanie aktualnego wykonania pętli, x jest zwiększany o jeden, sprawdzany jest warunek (x<=10), a ponieważ jest on spełniony, wykonywane są ponownie instrukcje zawarte w nawiasach klamrowych (linie 9 -17)
*pętle zagnieżdżone
13
Zagnieżdżenie pętli polega na umieszczeniu jednej pętli w drugiej - dla pętli for wygląda to następująco:
for (instrukcja_inicjujaca1; wyrazenie_warunkowe1; instrukcja_kroku1) {
instrukcje1;
for (instrukcja_inicjujaca2; wyrazenie_warunkowe2; instrukcja_kroku2) {
instrukcje2;
} }
Załóżmy, że pętla zewnętrza wykonuje się w-krotnie, a pętla wewnętrza k-krotnie.
Istota zagnieżdżenia w powyższym przykładzie polega na tym, że w każdym pojedynczym obiegu pętli zewnętrznej wykonają się jednokrotnie instrukcje1 oraz pętla wewnętrza, przy czym pętla wykona się od początku (instrukcji_inicjującej2) aż do niespełnienia wyrażenia_warunkowego2, czyli k-krotnie (instrukcje2 wykonają się k-krotnie). W tej sytuacji po wyjściu z obu pętli instrukcje2 wykonają się łącznie w*k-krotnie (dla każdego w, po k-razy).
Przydatne przy przetwarzaniu tablic n-wymiarowych.
Pętla zewn. Pętla wew.
liczby pseudolosowe
14
Liczby losowe w C++:
• Liczby „losowe” generowane przez komputer wyznaczane są na podstawie przyjętego algorytmu (wzoru generacyjnego), więc są przewidywalne. Z tego powodu nazywane są liczbami pseudolosowymi.
• W C++ za generację takich liczb odpowiada m.in. funkcja rand(), która zwraca liczbę całkowitą z przedziału od 0 do RAND_MAX (wykorzystywany jest równomierny rozkład prawdopodobieństwa). Makro RAND_MAX wynosi co najmniej 32 767.
• W celu zapewnienia zmienności generowanych liczb pomiędzy uruchomieniami programu konieczna jest inicjalizacja generatora liczbą o charakterze zmiennym, do czego dobrze nadaje się aktualny czas. Za inicjalizację odpowiada funkcja srand().
• deklaracje funkcji srand() i rand() znajdują się w pliku nagłówkowym cstdlib
Przykład 6. Napisz program, który wygeneruje trzy liczby losowe: pierwsza z przedziału od 0 do 99, druga z przedziału od 1 do 100, trzecia z przedziału od 1985 do 2014.
liczby pseudolosowe
15
Nr linii Opis
12 plik nagłówkowy dla funkcji time() zwracającej aktualny czas (poczytaj jej opis na stronie http://www.cplusplus.com/reference/)
7 inicjalizacja generatora wartością aktualnego czasu
8 Wynikiem dzielenia modulo X%Y jest liczba z przedziału <0, Y-1>, zatem dzielenie rand() % 100 zwraca liczbę z przedziału <0, 99>
9 Przesunięcie przedziału o 1, czyli <0, 99> + 1 --> <1, 100>
10 Przesunięcie przedziału o 1985, czyli <0, 29> + 1985 --> <1985, 2014>
Zadania
16
Zadanie 1. Napisz program, który za pomocą pętli for wyświetla liczby całkowite od 1 do 20. Otrzymaj rezultat:
Zadanie 2. Zmodyfikuj program z zadania 1, tak aby wykorzystać pętlę while.
Zadanie 3. Zmodyfikuj program z zadania 1, tak aby wykorzystać pętlę do while.
Zadanie 4. Napisz program, który prosi użytkownika o podanie liczby całkowitej, większej od zera. Jeśli liczba nie spełnia tych warunków program powinien prosić o podanie poprawnej liczby aż do skutku. Następnie program powinien obliczyć kwadrat tej liczby i wyświetlić uzyskany rezultat. Wskazówka – wykorzystaj funkcję round() z biblioteki cmath. Przykładowy wynik:
Zadania
17
Zadanie 5. Zmodyfikuj program z zadania 7, tak aby granice przedziału były wprowadzane przez użytkownika (wykorzystaj cin lub scanf).
Zadanie 6. Zmodyfikuj program kalkulator (wykorzystujący switch) tak, aby działał on w pętli while. Wpisanie litery k kończy działanie programu (dodaj tę opcję do menu).
Zadanie 7. Napisz program, który za pomocą pętli for sumuje liczby parzyste w przedziale od 1 do 100.
Zadanie 8. Zmodyfikuj program z zadania 7, tak aby wykorzystać pętlę while.
Zadanie 9. Zmodyfikuj program z zadania 7, tak aby wykorzystać pętlę do while.
Zadanie 10. Napisz program, który za pomocą pętli for znajduje największą i najmniejszą liczbę ze zbioru n liczb losowych z przedziału od 0 do 99 oraz oblicza ich średnią. Liczbę n wprowadza użytkownik.
Zadanie 11. Sformułuj algorytm i napisz program obliczający sumę ciągu N liczb wprowadzanych do komputera. Ilość liczb jest pierwszą wprowadzaną wartością i poprzedza wprowadzane liczby. Przedstaw schemat blokowy algorytmu.
Zadanie 12. Napisz program obliczający wartość silni dla liczby n wprowadzanej do programu z wykorzystaniem funkcji scanf.
*Zadanie 13. Użyj pętli zagnieżdżonych, aby uzyskać następujący wzór:
$
$$
$$$
$$$$
Zadania
18
*Zadanie 14. Napisz program, który prosi użytkownika (do skutku) o podanie liczby n całkowitej, większej od zera. Program następnie wyświetla numery indeksów macierzy o rozmiarze n x n. Wskazówka – wykorzystaj pętle zagnieżdżone:
zewnętrza zmienia numer wiersza, wewnętrza numer kolumny (dla danego wiersza). Przykładowy rezultat:
19
Literatura:
[1] Grębosz J., Opus Magnum C++, Helion, Gliwice, 2018
[2] Prata S., Język C++ Szkoła programowania, Helion, Gliwice, 2013 [3] Prata S., Język C Szkoła programowania, Helion, Gliwice, 2012