This is an old revision of the document!
for
, while
i do-while
.
Pętla for
(ang. dla) pozwala na wykonywanie fragmentu programu określoną ilość razy.
Wykorzystuje ona trzy wyrażenia rozdzielone średnikami:
Pętla for
kończy się jedną instrukcją prostą lub złożoną.
Pętla for
to “pętla z warunkiem wejścia”, co oznacza że pętla może nie wykonać się ani razu, jeśli na samym początku warunek nie został spełniony.
Ogólna postać pętli for
:
for (inicjalizacja; test; aktualizacja) instrukcja
Schemat blokowy a kod w C
Przykład 1 – Wielokrotne wypisywanie na ekran
#include <stdio.h> int main() { int i; for(i = 1; i <= 10; i = i + 1) { printf("%d\n", i); } return 0; }
Przykład 2 – Obliczanie silnii
#include <stdio.h> int main() { int s, n, i; printf("Podaj liczbę naturalną n: "); scanf("%d", &n); s = 1; for(i = 2; i <= n; i = i + 1) { s = s * i; } printf("%d! = %d\n", n, s); return 0; }
Zadanie FOR-1
Napisz program, który oblicza sumę liczb całkowitych z zakresu od 1 do 10 przy pomocy pętli for
.
Oczekiwany wynik: 55
Zadanie FOR-2
Napisz program, który wczytuje zadane przez użytkownika dwie liczby całkowite – $a$ i $b$ – i oblicza sumę liczb całkowitych z przedziału $\langle a, b \rangle$. Przyjmij, że $a \leq b$ (nie sprawdzaj tego w programie).
Przykład: Dla liczb $a = 3, b = 5$ poprawnym wynikiem jest $3+4+5=12$.
Priorytet operatorów oznacza to samo, co kolejność działań w matematyce – operator o wyższym priorytecie zostanie wykonany najpierw, a gdy obok siebie stoją, to operacje są wykonywane od lewej do prawej (chyba, że sam operator działa inaczej, o czym za chwilę).
Przykładowo – w matematyce – wyrażenie $(2+2 \cdot 2) \cdot 2$ zostanie obliczone w następujących krokach:
Dlaczego tak? Ponieważ – mówiąc językiem programisty – nawiasy mają najwyższy priorytet, a mnożenie ma wyższy priorytet od dodawania.
Zapoznaj się z tabelą priorytetów operatorów w języku C (uwaga: wielu z zawartych w niej operatorów jeszcze nie znasz, lecz część z nich wprowadzimy sukcesywnie na kolejnych zajęciach).
Zwróć uwagę na kolumnę Associativity, czyli “kierunek wiązania”. Oznacza to, która strona operatora zostanie obliczona w pierwszej kolejności (np. Left-to-right oznacza, że najpierw obliczona zostanie lewa strona operatora) i niejako “w którą stronę działa operator” – przykładowo operator przypisania =
przypisuje wartość stojącą po jego prawej stronie zmiennej stojącej po lewej stronie, zatem jego kierunek wiązania to Right-to-Left.
Tak więc, można stwierdzić, że każde wyrażenie w języku C ma pewną wartość, obliczoną zgodnie z priorytetami i kierunkami wiązania operatorów.
Nie musisz pamiętać całej tej terminologii, lecz musisz kojarzyć o co w tym wszystkim chodzi.
Podobnie jak w matematyce, możesz w wyrażeniach użyć nawiasów, aby obliczenia były wykonywane w odpowiedniej kolejności:
2 + 2 * 2 == 6 (2 + 2) * 2 == 8
Pętla while
wykonuje instrukcję dopóty, dopóki spełniony jest warunek testowy (tzn. wyrażenie podane jako warunek ma wartość niezerową).
Ogólna postać:
while (wyrażenie_testowe) instrukcja
Pętla while
to pętla z warunkiem wejścia, co oznacza że warunek sprawdzany jest przed każdym jej obiegiem (także pierwszym).
Zazwyczaj zechcesz gdzieś wewnątrz pętli zmieniać wartości zmiennych tak, aby warunek wejścia stał się fałszywy :)
Przykład
Obliczanie silni za pomocą pętli while
– porównaj z programem wykonującym to samo zadanie z użyciem pętli for
.
#include <stdio.h> int main() { int s, n, i; printf("Podaj liczbe naturalna n: "); scanf("%d", &n); s = 1; i = 1; while (i <= n) { s = s * i; i = i + 1; } printf("%d! = %d\n", n, s); return 0; }
Która pętla Twoim zdaniem lepiej nadaje się do tego zadania?
Dobra praktyka programistyczna mówi:
Stosuj pętlę for
tylko wtedy, gdy dokonujesz zarówno inicjalizacji, jak i aktualizacji. We wszystkich innych przypadkach lepiej (czytelniej) użyć pętli while
.
Zadanie WHILE-1
Napisz program obliczający wynik $n \cdot k$ dla zadanych liczb całkowitych $n$ i $k$ bez korzystania z mnożenia. Użyj pętli while
.
Wskazówka: $n \cdot k = \underbrace{n + n + \ldots + n}_{k \text{ razy}}$
Pętla do-while
, podobnie jak pętla while
wykonuje instrukcję dopóki spełniony jest warunek testowy.
Ogólna postać:
do instrukcja while (wyrażenie_testowe);
Zwróć uwagę na średnik występujący po
while (...)
!
Różnica między dwoma typami pętli while
polega na tym, że do-while
to pętla z warunkiem wyjścia – oznacza to, że warunek sprawdzany jest po każdym obiegu pętli (a więc petla wykona się co najmniej raz).
Przykład
#include <stdio.h> int main(void) { int i = 0; printf("Poczatek petli \n\n"); do { printf("Wartosc zmiennej 'i' wynosi %d \n", i); i = i + 1; } while (i < 5); printf("\nKoniec petli"); return 0; }
W praktyce programiści starają się unikać stosowania do-while
, gdyż:
do-while
pętlą while
.
Uogólnienie powyższej zasady brzmi:
Lepiej stosować pętle z warunkiem wejścia (while
, for
), a nie wyjścia (do-while
). (z tych samych powodów, co podane powyżej)
Zadanie 1
Napisz program, który prosi użytkownika o podanie liczby całkowitej większej od $0$. Program powinien zakończyć działanie dopiero wtedy, gdy użytkownik podał poprawną wartość.
Zadanie 2
Napisz program losujący liczbę z przedziału $\langle 0, 100 \rangle$ tak długo aż wylosuje liczbę z przedziału $\langle 10, 15 \rangle$.
Do losowania liczb służy funkcja rand() z biblioteki stdlib.h.
Zapoznaj się z materiałem dostępnym tu: Debugging
(poziom trudności: )
Napisz program sprawdzający w naiwny sposób (czyli: najprostszy), czy zadana przez użytkownika liczba jest liczbą pierwszą.
Wykorzystaj pętlę for
i operator modulo (%
).
Wskazówka 1: Najpierw zastanów się, jakie warunki musi spełniać liczba, aby była pierwsza (inaczej: jak “ręcznie” sprawdzić, czy liczba jest pierwsza).
Wskazówka 2: Przy konstruowaniu warunku pętli bądź instrukcji warunkowych pomocne mogą Ci być prawa De Morgana.
(poziom trudności: )
Napisz program, który wypisze na ekran taki fragment:
1 2 3 2 3 1 3 1 2
Użyj pętli for
.
Wskazówka 1: Pętle, podobnie jak instrukcje warunkowe, można zagnieżdżać. Pętla wewnętrzna wykonuje swój pełny zakres powtórzeń w każdym cyklu pętli zewnętrznej.
Wskazówka 2: Przydatny może być operator “modulo”…
(poziom trudności: )
Napisz program, który dla zadanej liczby całkowitej obliczy sumę jej cyfr.
Przykład: dla $196$ poprawnym wynikiem jest $1 + 9 + 6 = 16$
Wskazówka: Wykorzystaj własność dzielenia i obcięcia w języku C.
(poziom trudności: )
Napisz program obliczający pierwiastek kwadratowy zadanej liczby metodą babilońską (kroki 1-3). Przerwij obliczenia, gdy różnica między kolejnymi przybliżeniami jest mniejsza niż $10^{-4}$.
Wskazówka: Jako pierwsze oszacowanie możesz przyjąć $\sqrt{S} \approx S$
Być może zastanawiasz się: Po co ręcznie obliczać pierwiastek? Przecież można skorzystać z wbudowanej funkcji sqrt()!
Owszem, lecz jeśli nie potrzebujesz mega-dużej dokładności, to metodą babilońską uzyskasz wystarczająco dobry wynik o wiele, wiele szybciej.