6. Pętle while. Przykłady

Podobne dokumenty
7. Pętle for. Przykłady

5. Rekurencja. Przykłady

4. Funkcje. Przykłady

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

2. Zmienne i stałe. Przykłady Napisz program, który wypisze na ekran wynik dzielenia 281 i 117 w postaci liczby mieszanej (tj. 2 47/117).

do instrukcja while (wyrażenie);

Programowanie - wykład 4

3. Instrukcje warunkowe

for (inicjacja_warunkow_poczatkowych(końcowych); wyrazenie_warunkowe; wyrazenie_zwiekszajace(zmniejszające)) { blok instrukcji; }

for (inicjacja_warunkow_poczatkowych; wyrazenie_warunkowe; wyrazenie_zwiekszajace) { blok instrukcji; }

Rekurencja (rekursja)

Pętla for. Wynik działania programu:

Iteracje. Algorytm z iteracją to taki, w którym trzeba wielokrotnie powtarzać instrukcję, aby warunek został spełniony.

WHILE (wyrażenie) instrukcja;

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

1. Wypisywanie danych

WHILE (wyrażenie) instrukcja;

Schematy blokowe I. 1. Dostępne bloki: 2. Prosty program drukujący tekst.

Podstawy programowania. Wykład: 4. Instrukcje sterujące, operatory. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Pętle i tablice. Spotkanie 3. Pętle: for, while, do while. Tablice. Przykłady

Programowanie strukturalne i obiektowe. Funkcje

Warunki logiczne instrukcja if

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Algorytmy i struktury danych. Wykład 4

Pzetestuj działanie pętli while i do...while na poniższym przykładzie:

Lekcja : Tablice + pętle

REKURENCJA W JĘZYKU HASKELL. Autor: Walczak Michał

Paradygmaty programowania

INFORMATYKA Z MERMIDONEM. Programowanie. Moduł 5 / Notatki

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Programowanie komputerowe. Zajęcia 2

Podstawy programowania. Wykład: 13. Rekurencja. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Programowanie komputerowe. Zajęcia 3

Jak zawsze wyjdziemy od terminologii. While oznacza dopóki, podczas gdy. Pętla while jest

Język C, tablice i funkcje (laboratorium, EE1-DI)

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Wieczorowe Studia Licencjackie Wrocław, Wykład nr 6 (w oparciu o notatki K. Lorysia, z modyfikacjami) Sito Eratostenesa

ALGORYTMY. 1. Podstawowe definicje Schemat blokowy

ALGORYTMY I STRUKTURY DANYCH

Nazwa implementacji: Nauka języka Python pętla for. Autor: Piotr Fiorek

ALGORYTMY. 1. Podstawowe definicje Schemat blokowy

ALGORYTMY Algorytm poprawny jednoznaczny szczegółowy uniwersalny skończoność efektywność (sprawność) zmiennych liniowy warunkowy iteracyjny

Pętle. for, while, do... while, foreach. Materiał pomocniczy do kursu Podstawy programowania Autor: Grzegorz Góralski ggoralski.

Programowanie i techniki algorytmiczne

wagi cyfry pozycje

Wstęp do programowania

a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a[10]

Zadeklarowanie tablicy przypomina analogiczną operację dla zwykłych (skalarnych) zmiennych. Może zatem wyglądać na przykład tak:

Wstęp do Informatyki zadania ze złożoności obliczeniowej z rozwiązaniami

Opis zagadnieo 1-3. Iteracja, rekurencja i ich realizacja

Podstawy Programowania Podstawowa składnia języka C++

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk

Programowanie komputerowe. Zajęcia 1

1. Napisz program, który wyświetli Twoje dane jako napis Witaj, Imię Nazwisko. 2. Napisz program, który wyświetli wizytówkę postaci:

Wstęp do informatyki- wykład 7

Wiadomości wstępne Środowisko programistyczne Najważniejsze różnice C/C++ vs Java

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Programowanie - instrukcje sterujące

1 Podstawy c++ w pigułce.

Temat 20. Techniki algorytmiczne

Każde wykonanie bloku instrukcji nazywamy pojedynczym przebiegiem lub iteracją pętli.

Struktura pliku projektu Console Application

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Część 4 życie programu

Instrukcje warunkowe i skoku. Spotkanie 2. Wyrażenia i operatory logiczne. Instrukcje warunkowe: if else, switch.

Wstęp do informatyki- wykład 6

Podstawy programowania 2. Temat: Funkcje i procedury rekurencyjne. Przygotował: mgr inż. Tomasz Michno

Programowanie w Baltie klasa VII

Instrukcje sterujące

Część XV C++ Ćwiczenie 1

Podstawy programowania funkcjonalnego

Konstrukcje warunkowe Pętle

1. Informatyka - dyscyplina naukowa i techniczna zajmująca się przetwarzaniem informacji.

Zapisywanie algorytmów w języku programowania

Algorytmy i struktury danych

Program znajduje największa lub najmniejsza z podanych liczb. Liczby podajemy dopóki nam sie nie znudzi.

Niezwykłe tablice Poznane typy danych pozwalają przechowywać pojedyncze liczby. Dzięki tablicom zgromadzimy wiele wartości w jednym miejscu.

Materiały dla finalistów

Wskazówki dotyczące zmiennych, tablic i procedur 1

Instrukcja wyboru, pętle. 2 wykład. Podstawy programowania - Paskal

Metody Metody, parametry, zwracanie wartości

Lekcja 3: Pierwsze kroki z Pythonem. Pętle

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje:

Tablice mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011

LISTA 5. C++ PETLE for, while, do while

Zaawansowane algorytmy i struktury danych

Funkcje. Deklaracja funkcji. Definicja funkcji. Wykorzystanie funkcji w programie.

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Wstęp do programowania

PROGRAMOWANIE W C++ ZADANIA

Liczby rzeczywiste. Działania w zbiorze liczb rzeczywistych. Robert Malenkowski 1

Wstęp do informatyki- wykład 12 Funkcje (przekazywanie parametrów przez wartość i zmienną)

Wstęp do Programowania, laboratorium 02

Zadanie 1. Zmiana systemów. Zadanie 2. Szyfr Cezara. Zadanie 3. Czy liczba jest doskonała. Zadanie 4. Rozkład liczby na czynniki pierwsze Zadanie 5.

Podstawy Programowania C++

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Wykład 4. Określimy teraz pewną ważną klasę pierścieni.

Transkrypt:

6. Pętle while Przykłady 6.1. Napisz program, który, bez użycia rekurencji, wypisze na ekran liczby naturalne od pewnego danego n do 0 włącznie, w kolejności malejącej, po jednej liczbie na linię. Uwaga! Kod rozwiązania znajduje się niżej. Funkcje rekurencyjne w językach takich jak C++, Java czy Python, zajmują bardzo dużo pamięci. Dodatkowo ich zapotrzebowanie na pamięć często rośnie wraz ze wzrostem wartości przekazywanych argumentów. Na przykład funkcja odliczod zdefiniowana w poprzednim rozdziale, gdy wywołana z argumentem 1000, wywoła samą siebie z argumentem 999, następnie 998, 99 itd. aż do 0. Oznacza to 1001 wywołań tej samej funkcji, a każde wywołanie zajmuje pewną ilość miejsca w pamięci (zależnie od liczby i typów argumentów). Uwaga! Używanie rekurencji wymaga pewnego stopnia ostrożności. Wywołanie funkcji rekurencyjnej z wieloma argumentami może prowadzić do tzw. przepełnienia stosu. Nie oznacza to jednak, że rekurencja nie jest przydatna. Istnieją programy, które o wiele łatwiej napisać jest rekurencyjnie niż iteracyjnie (tj. przy użyciu pętli). Istnieją wręcz obliczenia, których bez rekurencji wykonać się nie da (np. funkcja Ackermanna). Dlatego zamiast mnożyć wywołania, z których każde posiada swój zestaw argumentów, możemy użyć zmiennej, której wartość będziemy wielokrotnie zmieniać i za każdym razem wykorzystywać jej wartość do naszych obliczeń. Do takiego wielokrotnego wykonywania tego samego fragmentu kodu służą pętle. W programie powyżej wykorzystana jest pętla while, która powtarza wykonywanie danego jej fragmentu kodu tak długo, jak długo spełniony jest pewien dany warunek. Pętla while wyglądem przypomina wyrażenie if. Najpierw umieszczamy słowo kluczowe while, następnie w nawiasach okrągłych warunek, a na końcu w nawiasach klamrowych fragment kodu do powtarzania. 41

Uwaga! Pętla while przypomina wyrażenie if nie tylko wyglądem, ale i zachowaniem. Wyrażenie if sprawdza warunek, po czym wykonuje fragment kodu, jeżeli warunek był spełniony lub omija go w przeciwnym wypadku. Podobnie pętla while sprawdza warunek, po czym albo wykonuje kod (warunek jest spełniony) albo go pomija. Różnica polega na tym, że po wykonaniu przypisanego fragmentu kodu, pętla while ponownie sprawdza warunek i decyduje, czy wykonać kod itd. aż warunek nie będzie spełniony. Spójrzmy teraz na rozwiązanie przykładu: 5 int n; 6 cin >> n; 8 while (n >= 0) { 9 cout << n << endl; 10 n = n-1; 11 } 12 1 return 0; 14 } W liniach 5-6 pobieramy od użytkownika wartość liczby n i przechowujemy ją w zmiennej n. Mimo, że kod ten znajduje się poza pętlą, to dokonuje on inicjalizacji pętli, czyli ustawia wartości zmiennych, którymi pętla będzie się posiłkować. Następnie w linii 8 znajduje się warunek. Pętla będzie wykonywana tak długo, jak warunek jest spełniony. Chcemy wypisywać kolejne liczby aż zejdziemy poniżej 0, stąd warunek n >= 0. Następnie w linii 9 wypisujemy obecną wartość n, a w linii 10 zmniejszamy tę wartość o 1. W ten sposób następna iteracja (powtórzenie pętli) wykonywana będzie dla liczby o jeden mniejszej. Nazywamy to krokiem pętli. Kod przy pętli wykonywany będzie po kolei dla coraz mniejszych wartości n, aż dojdzie do 1, dla którego warunek nie będzie spełniony i wykonywanie pętli zakończy się. 42

6.2. Napisz program, który wypisze na ekran kolejne liczby naturalne od 0 do pewnego danego n, bez użycia rekurencji. 5 int n; 6 cin >> n; 8 int i = 0; 9 while (i <= n) { 10 cout << i << endl; 11 i = i+1; 12 } 1 14 return 0; 15 } Jeżeli chcemy wypisać liczby w przeciwnym kierunku, tj. od 0 do n, nie wystarczy nam już tylko jedna zmienna n. Musimy dołożyć do niej kolejną zmienną i, która zapamiętuje jaka następna liczba powinna zostać wypisana. Zmienna ta pełni rolę tzw. iteratora, czyli zmiennej opisującej obecne położenie w pewnym zestawie liczb (tutaj kolejne liczby naturalne od 0 do n). Pozwala to zrobić bez wprowadzania zmian do tego zestawu (tutaj n pozostaje bez zmian, w odróżnieniu od poprzedniego zadania). 6.. Napisz program, który obliczy sumę liczb od 1 do n włącznie, bez użycia rekurencji ani wzoru Gaussa (tj. n(n+1) 2 ). 5 int n; 6 cin >> n; 8 int i = 1; 9 int suma = 0; 10 while (i <= n) { 11 suma = suma + i; 12 i = i+1; 1 } 4

14 15 cout << suma << endl; 16 return 0; 1 } Program ten jest bardzo podobny do programu z poprzedniego przykładu. Dodana została tu zmienna suma, która przechowuje dotychczasową sumę liczb. Zmienną, która zapamiętuje dotychczasowy wynik działań nazywamy akumulatorem. Początkowa wartość tej zmiennej (linia 9) wynosi 0, jako że nie zsumowaliśmy jeszcze żadnych liczb, a suma niczego wynosi 0. Następnie w pętli (linie 10-1) kolejno przechodzimy po wszystkich liczbach od 1 do n włącznie. Robimy to tak, jak w poprzednim zadaniu, z tą różnicą, że tym razem zamiast wypisywać każdą kolejną liczbę, to dodajemy jej wartość do zmiennej suma (linia 11). Stąd po zakończeniu działania pętli, zmienna suma zawierać będzie sumę wszystkich liczb od 1 do n włącznie. Jej początkowa wartość, zero, powiększona została kolejno o wartość każdej kolejnej liczby naturalnej. To daje nam końcową wartość 0 + 1 + 2 +... + (n 1) + n, czyli wymaganą sumę. Zostaje nam tylko wypisać wynik (linia 15). 6.4. Napisz program, który będzie pobierał od użytkownika liczby aż do napotkania zera, a następnie wypisze na ekran ile liczb pobrał (wliczając końcowe zero). 5 int ile = 0; 6 int n = 1; 8 while (n!= 0) { 9 cin >> n; 10 ile = ile + 1; 11 } 12 1 cout << ile << endl; 14 15 return 0; 16 } W tym programie wewnątrz pętli pobieramy kolejne wartości do zmiennej n i zwiększamy wartość zmiennej ile. 44

Ta druga wartość jest naszym akumulatorem, jako że zapamiętuje ile liczb pobraliśmy do tej pory. Początkowo jest to 0 (linia 5). Następnie z każdym pobraniem kolejnej liczby wartość ta zwiększa się o 1 (linia 10), jako że pobraliśmy o jedną liczbę więcej niż dotychczas (linia 9). Początkowa wartość n wynosi 1. Dokładna wartość nie ma znaczenia, jako że i tak zostanie nadpisana. Ważne jest jedynie to, żeby była różna od 0, aby warunek pętli przy pierwszej iteracji był spełniony. Wewnątrz pętli pobieramy kolejne wartości i zwiększamy wartość akumulatora. Uwaga! Warunek pętli NIE jest magicznym strażnikiem, który przerwie działanie pętli w momencie, w którym warunek nie będzie dłużej spełniony. Warunek pętli jest sprawdzany tylko i wyłącznie na początku iteracji! Stąd po pobraniu 0 w linii 9, linia 10 wciąż zostanie wykonana. Dopiero wtedy zakończy się obecna iteracja, a na początku kolejnej sprawdzony zostanie warunek. 6.5. Napisz program, który wypisze k pierwszych potęg 2, zaczynając od 2 0, gdzie k jest dane przez użytkownika. Uwaga! Są dwa sposoby na wykonanie tego zadania. Pierwszy z nich, z użyciem cmath (pętlą przechodząc po wykładnikach i obliczając potęgi przy użyciu pow) spróbuj napisać samodzielnie. Drugi sposób pokazany jest poniżej. 5 int k; 6 cin >> k; 8 int potega = 1; 9 while (k > 0) { 10 cout << potega << endl; 11 potega = potega*2; 12 k = k-1; 1 } 14 15 return 0; 16 } 45

Akumulator nie musi być za każdym razem obliczany przez sumowanie, możemy używać również mnożenia. W przypadku tego programu, akumulatorem jest zmienna potega, która zapamiętuje wartość kolejnej potęgi do wypisania. Za każdą iteracją zwiększana jest dwukrotnie, co daje nam wartość kolejnej potęgi. Z kolei zmienna k opisuje ile jeszcze potęg pozostało nam do wypisania. Jeżeli osiągnie ona 0, oznacza to, że nie zostało nam już nic i możemy zakończyć działanie pętli, a następnie programu. Zwróć też uwagę, że zmienna ta jest za każdą iteracją zmniejszana, a nie zwiększana, jako że liczba potęg pozostałych do wypisania zmniejsza się za każdym razem. 6.6. Napisz program, który obliczy sumę n danych liczb. Program powinien najpierw pobrać liczbę n, a następnie n liczb, po czym wypisać ich sumę. 5 int n; 6 cin >> n; 8 int i = 0; 9 int suma = 0; 10 while (i < n) { 11 int k; 12 cin >> k; 1 14 suma = suma + k; 15 i = i + 1; 16 } 1 18 cout << suma; 19 return 0; 20 } Często zdarzać się będzie, że będziemy potrzebowali pobrać od użytkownika pewien ciąg liczb o określonej przez użytkownika długości. Co prawda w następnym rozdziale poznamy krótszy sposób zapisania programu powyżej, jednak warto już teraz zrozumieć i zapamiętać ogólny schemat pobierania n liczb. Najpierw musimy oczywiście wiedzieć, ile liczb musimy pobrać. Stąd zaczynamy od stworzenia zmiennej n i pobrania jej wartości od użytkownika (linie 5-6). Następnie tworzymy zmienną i pełniącą funkcję iteratora, która zapamiętuje ile liczb zostało już pobranych (linia 8). Początkowo jest to oczywiście 0. W tym przypadku tworzymy 46

również akumulator suma do przechowywania sumy pobranych już liczb, ale nie jest on częścią ogólnego wzorca. Pętla będzie działać tak długo, jak liczba pobranych liczb (i) jest mniejsza od liczby wszystkich liczb, jakie mieliśmy pobrać (n), stąd warunkiem pętli (linia 10) jest i < n. Wewnątrz pętli, za każdą iteracją tworzymy zmienną i pobieramy do niej liczbę (linie 11-12). Uwaga! Zmienną do której pobieramy liczbę w pętli możemy stworzyć przed rozpoczęciem pętli, a nie w środku. W ten sposób tworzymy tylko jedną zmienną, a nie n zmiennych, z których każda istnieje tylko w czasie swojej iteracji. Łamie to jednak zasadę zmienne tworzymy tak późno jak tylko możliwe. Teoretycznie stworzenie zmiennej przed pętlą prowadzi do zmniejszonego zużycia pamięci. W praktyce nowoczesne kompilatory i tak potrafią wykryć przypadek taki jak w kodzie wyżej i użyć dla każdej z tych n zmiennych tego samego miejsca w pamięci. W końcu musimy wykonać jakieś działanie na pobranej liczbie, tutaj dodać ją do dotychczasowej sumy (linia 14), a następnie zwiększyć wartość iteratora (linia 15). Po zakończeniu działania pętli, zmienna suma zawierać będzie wartość sumy n pobranych od użytkownika liczb, dlatego wypisujemy ją (linia 18) i kończymy działanie programu. Pytania 6.1. Porównaj kod z przykładu 6.1 z funkcją rekurencyjną odliczod z poprzedniego rozdziału, wykonującą to samo zadanie. Zwróć uwagę na podobieństwa i różnice między nimi. 6.2. Skąd bierze się różnica w warunkach znajdujących się w obu tych programach (n < 0 w funkcji rekurencyjnej, n >= 0 w pętli)? 6.. Dlaczego zmienna n w przykładzie 6.4 ma przypisaną początkową wartość, jeżeli jest ona niemal natychmiast nadpisywana w pętli? Czy możemy tę wartość dowolnie zmienić? 6.4. W poprzednim rozdziale zwrócona była uwaga, aby unikać == i!= w warunkach pętli, a w zamian używać nierówności tam, gdzie tylko jest to możliwe. Dlaczego więc w przykładzie 6.4 warunek to n!= 0? Czy możemy go zamienić na jakąś nierówność? Jeżeli tak, jaką? Jeżeli nie, dlaczego? 4

6.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 = 5; int i = 0; 4 int k; 5 while (i < n) { 6 cin >> k; i = i + 1; 8 } 9 cout << k; 10 11 // Fragment 2 12 int n = 5; 1 int i = 0; 14 while (i < n) { 15 int k; 16 cin >> k; 1 i = i + 1; 18 } 19 cout << k; Zadania Uwaga! W rozwiązaniach zadań poniżej, o ile nie zaznaczono inaczej, nie używaj cmath ani rekurencji. 6.1. Napisz program, który wypisze na ekran liczby nieparzyste od danego n do 1 włącznie, w kolejności malejącej. Zwróć uwagę, że n może być parzyste musisz to sprawdzić przed wykonaniem pętli i odpowiednio zmienić wartość n, aby było nieparzyste. 6.2. Napisz program, który wypisze k pierwszych wielokrotności 10, gdzie k jest dane przez użytkownika. Za pierwszą wielokrotność 10 uznajemy 10. 6.. Napisz program, który wypisze reszty z dzielenia liczby n danej przez użytkownika, przez wszystkie kolejne liczby naturalne od 1 do n włącznie. 48

6.4. Napisz funkcję, który znajdzie liczbę dzielników danej liczby całkowitej (jeżeli jest to dla ciebie zbyt trudne, rozwiąż najpierw poprzednie zadanie). Następnie napisz program, który przy użyciu tej funkcji będzie w nieskończoność wypisywał kolejne liczby pierwsze, zaczynając od 2. 6.5. Napisz program, który obliczy wartość silni z danej przez użytkownika liczby n. Dla przypomnienia: silnia to iloczyn kolejnych liczb naturalnych od 1 do n włącznie. 6.6. Zmodyfikuj program z przykładu 6.5 tak, aby obliczał i wypisywał wyłącznie wartość k-tej potęgi 2. Wymaga to wyłącznie zmiany położenia jednej linii kodu. 6.. Napisz program, który obliczy n k, gdzie n i k są dane przez użytkownika. 6.8. Napisz program, który policzy sumę n pierwszych liczb trójkątnych. Liczba trójkątna to liczba kul, które potrzebne są do zbudowania trójkąta równobocznego o danej podstawie. Kolejne liczby trójkątne to 1,, 6, 10, 15, 21, 28 itd. 6.9. Napisz program, który pobierze od użytkownika n liczb (gdzie n jest dane), a następnie wypisze na ekran ich średnią arytmetyczną. 6.10. Napisz program, który pobierze od użytkownika n liczb, a natępnie wypisze na ekran najmniejszą z nich. Podpowiedź: potrzebujesz zmiennej, która zapamiętywać będzie wartość najmniejszej z dotychczas pobranych liczb. Jej wartość powinna być zmieniana tylko wtedy, gdy nowo pobrana liczba jest mniejsza od dotychczasowego minimum. Rozszerzenie 6.1. Napisz program, który będzie znajdował i wypisywał na ekran rozkład danej liczby na czynniki pierwsze. Postaraj się, aby twój program działał jak najszybciej. Na przykład rozkład na czynniki pierwsze liczby 999 999 9 (która jest pierwsza) powinien pojawiać się na ekranie niemal natychmiast (kilka sekund to za długo). 6.2. Regresja liniowa. Napisz program, który dla danego zestawu punktów na płaszczyznie, znajdzie linię prostą, której sumaryczna odległość od każdego z punktów jest jak najmniejsza. 6.. Klastrowanie algorytmem k-średnich. Napisz program, który dany zestaw punktów na płaszczyznie podzieli na dwa zestawy takie, że sumaryczna odległość wszystkich punktów od środka ich zestawu jest jak najmniejsza. 49