User Tools

Site Tools


dydaktyka:cprog:2016:loops

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
dydaktyka:cprog:2016:loops [2016/10/20 09:00]
pkleczek
— (current)
Line 1: Line 1:
-====== ​ Pętla for, pętla "​while",​ debuggowanie ====== 
  
-===== Cel laboratorium ===== 
- 
-  * Omówienie priorytetów operatorów. 
-  * Zapoznanie z pętlą ''​for'',​ ''​while''​ i ''​do-while''​. 
-  * Umiejętność posługiwania się //​debuggerem//​. 
- 
-===== Pętla "​for"​ ===== 
- 
-Pętla ''​for''​ (ang. //dla//) pozwala na wykonywanie fragmentu programu określoną ilość razy.  
- 
-Wykorzystuje ona trzy wyrażenia rozdzielone __średnikami__:​ 
-  * **inicjalizacja licznika** -- wykonywane jeden raz, zaraz przed pierwszą iteracją (obiegiem pętli) 
-  * **warunek** (test) -- obliczany __przed__ każdym potencjalnym wykonaniem pętli (jeśli wyrażenie to jest fałszywe, pętla zostaje zakończona) 
-  * **zmiana** (aktualizacja) -- obliczane __na końcu__ każdej iteracji 
- 
-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'':​ 
-<​code>​ 
-for (inicjalizacja;​ test; aktualizacja) 
-    instrukcja 
-</​code>​ 
- 
-**Schemat blokowy a kod w C** 
-^ Schemat blokowy ^ Kod w C ^ 
-| {{:​dydaktyka:​aisd:​2016:​iteration.png?​direct|}} | <code c> 
-int licz; 
-for (licz = WP; licz <= WK; licz = licz + 1) { 
-    instrukcja 
-} 
-</​code>​ Zwróć uwagę, że w języku C pętla for wykonuje się dopóki warunek **jest** spełniony (na sąsiednim schemacie blokowym mamy iterację dopóki warunek nie był spełniony). | 
- 
----- 
- 
-**Przykład 1 -- Wielokrotne wypisywanie na ekran** 
-<code c> 
-#include <​stdio.h>​ 
- 
-int main() 
-{ 
-    int i; 
- 
-    for(i = 1; i <= 10; i = i + 1) { 
-        printf("​%d\n",​ i); 
-    } 
- 
-    return 0; 
-} 
-</​code>​ 
- 
-**Przykład 2 -- Obliczanie silnii** 
-<code c silnia.c>​ 
-#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; 
-} 
-</​code>​ 
- 
----- 
- 
-**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 ===== 
- 
-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: 
-  - Obliczenie wartości w nawiasie: 
-    - Obliczenie $2 \cdot 2 = 4$ 
-    - Obliczenie $2 + 4 = 6$ 
-  - Obliczenie $6 \cdot 2 = 12$ 
- 
-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 [[http://​en.cppreference.com/​w/​c/​language/​operator_precedence|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:​ 
-<​code>​ 
-2 + 2 * 2 == 6 
-(2 + 2) * 2 == 8 
-</​code>​ 
- 
-/* 
----- 
- 
-**Zadanie 1** \\ 
-Napisz program sprawdzający,​ czy dla zadanej przez użytkownika liczby $x$ zachodzi $4 < x < 6$. \\ 
-Przetestuj swój program dla $x = 5$ oraz dla $x = 7$. 
- 
-*/ 
-===== Pętla "​while"​ ===== 
- 
-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ć: 
-<​code>​ 
-while (wyrażenie_testowe) 
-    instrukcja 
-</​code>​ 
- 
-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 [[http://​home.agh.edu.pl/​~pkleczek/​dokuwiki/​doku.php?​id=dydaktyka:​cprog:​2015:​conditionals#​petla_for|programem]] wykonującym to samo zadanie z użyciem pętli ''​for''​. 
-<code c> 
-#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; 
-} 
-</​code>​ 
- 
-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"​ ===== 
- 
-Pętla ''​do-while'',​ podobnie jak pętla ''​while''​ wykonuje instrukcję dopóki spełniony jest warunek testowy. 
- 
-Ogólna postać: 
-<​code>​ 
-do 
-    instrukcja 
-while (wyrażenie_testowe);​ 
-</​code>​ 
-:!: 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** 
-<code c> 
-#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; 
-} 
-</​code>​ 
- 
----- 
- 
-W praktyce programiści starają się unikać stosowania ''​do-while'',​ gdyż: 
-  * umieszczanie warunku na końcu pętli zmniejsza czytelność kodu, natomiast 
-  * bez trudu można tak zmienić kod, aby zastąpić pętlę ''​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''​).//​ (nbsp) [size=10](z tych samych powodów, co podane powyżej)[/​size] 
- 
----- 
- 
-**Zadanie DOWHILE-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 DOWHILE-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 [[http://​www.cplusplus.com/​reference/​cstdlib/​rand/?​kw=rand|rand()]] z biblioteki //​stdlib.h//​. 
- 
-===== Debugging ===== 
- 
-Zapoznaj się z materiałem dostępnym tu: [[dydaktyka:​cprog:​learning_resources:​debugging|Debugging]] 
- 
-===== Zadania podsumowujące ===== 
- 
-==== Zadanie DIGSUM ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​2/​4}}) 
- 
-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ść [[dydaktyka:​cprog:​2015:​data_types#​arytmetyka_liczb_w_c_-_pulapki|dzielenia i obcięcia w języku C]].// 
- 
-==== Zadanie PRIME ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​3/​4}}) 
- 
-Napisz program sprawdzający w [[http://​wcipeg.com/​wiki/​Naive_algorithm|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ć [[https://​pl.wikipedia.org/​wiki/​Prawa_De_Morgana|prawa De Morgana]].//​ \\ 
- 
-==== Zadanie BABSQRT ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​3/​4}}) 
- 
-Napisz program obliczający pierwiastek kwadratowy zadanej liczby [[https://​pl.wikipedia.org/​wiki/​Metody_obliczania_pierwiastka_kwadratowego#​Metoda_babilo.C5.84ska|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$ ;-) // 
- 
-[size=10]Być może zastanawiasz się: //Po co ręcznie obliczać pierwiastek?​ Przecież można skorzystać z wbudowanej funkcji [[http://​www.cplusplus.com/​reference/​cmath/​sqrt/​|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.[/​size] 
- 
-==== Zadanie SQUARE ==== 
- 
-([size=10]poziom trudności:​[/​size] {{stars>​4/​4}}) 
- 
-Napisz program, który wypisze na ekran taki fragment: 
-<​code>​ 
-1 2 3 
-2 3 1 
-3 1 2 
-</​code>​ 
-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"​...//​ 
dydaktyka/cprog/2016/loops.1476946830.txt.gz · Last modified: 2020/03/25 11:46 (external edit)