Instrukcje iteracji - pętle
Przegląd zagadnień
Często pewną instrukcję lub grupę instrukcji należ wykonać pewną określoną
ilość razy lub aż zostanie spełniony pewien warunek. W takich przypadkach
stosujemy specjalne konstrukcje językowe zwane pętlami. Pętle nazywane są
również instrukcjami iteracyjnymi. W przypadku pętli istnieje
niebezpieczeństwo, że się zapętli. Instrukcje są wykonywane w nieskończonej
pętli z powodu podania złego warunku wyjścia z pętli. Taką sytuację dobrze
ilustruje dowcip o programiście pod prysznicem:
Dlaczego programista zginął pod prysznicem?
Ponieważ zbyt dokładnie stosował się do instrukcji użycia szamponu, która
brzmiała: "Nanieść szampon na zmoczone włosy. Masuj. Spłucz. Powtórz."
Po skończeniu tego modułu studenci poznają następujące instrukcje iteracyjne:
while
for
do{..}while
Uwaga:
W języku C# istnieje jeszcze pętla foreach. Zostanie ona omówiona w
rozdziale szóstym.
Pętla while
Pierwszą instrukcją iteracyjną, która zostanie omówiona będzie instrukcja
while.
Instrukcja while ma następującą postać:
while(warunek)
instr;
gdzie warunek jest wyrażeniem logicznym, czyli czymś co może mieć wartość
true lub false. Instrukcja instr jest instrukcją, która będzie wykonywana
pewną ilość razy. Działanie pętli while jest następujące. Najpierw sprawdzana
jest wartość wyrażenia warunek. Jeżeli warunek ma wartość false,
wykonanie instrukcji instr jest pomijane i program przechodzi do
wykonywanie dalszych instrukcji. Jeżeli wyrażenie warunek ma wartość true,
instrukcja instr zostaje wykonana. Po wykonaniu instrukcji instr, wracamy
do sprawdzenia warunku. I znowu, jeżeli wyrażenie warunek ma wartość
false
, wykonywanie pętli zostaje przerwane, gdy wyrażenie warunek ma
wartość true, ponownie wykonywana jest instrukcja instr i po jej
wykonaniu następuje powrót do sprawdzania warunku.
Wcięcie użyte w powyższym kodzie oczywiście są opcjonalne, ale bardzo
zwiększają czytelność kodu.
Podobnie jak w przypadku instrukcji if, nie powinno się stawiać średnika tuż
za nawisem "zamykającym" warunek.
while(warunek) ;
instr1;
W powyższym kodzie w pętli wykonywana będzie instrukcja pusta, która nie
zmieni wartości wyrażenia warunek. Wynikiem tego może być zapętlenie.
Jeżeli w pętli while chcemy wykonywać ciąg instrukcji, instrukcje te
umieszczamy w bloku.
while(warunek)
{
instrukcja1;
...
instrukcjan;
}
Kara wypisania 100 razy na ekranie np. tekstu "Nie będę używał komórki na
zajęciach" przy pomocy pętli while może zostać wykonana w następujący
sposób:
...
int i = 0;
while(i < 100)
{
i++;
Console.WriteLine("{0}. Nie będę używał komórki na
¬zajęciach", i);
}
...
Pętla for
Pętla for ma następującą postać:
for(instr1; warunek; instr2)
instr3;
Schemat działania instrukcji for jest następujący. Na początku wykonywana jest
instrukcja instr1. Jest ona wykonywana tylko raz, podczas rozpoczęcia działania
pętli. Następnie jest sprawdzana wartość wyrażenia logicznego warunek. Gdy
warunek ma wartość false wykonywanie pętli zostaje zakończone. Jeżeli
wyrażenie warunek ma wartość true, to program przechodzi do wykonania
instrukcji instr3, a dopiero potem wykonuje instrukcję instr2. Po
wykonaniu instrukcji instr2 ponownie przechodzimy do sprawdzenia
wartości wyrażenia warunek i w zależności od jego wartości kontynuujemy
wykonanie pętli lub nie. Proszę zwrócić uwagę, że program nie wykonuje
instrukcji instr1 ponownie.
Podobnie jak w przypadku instrukcji while, jeżeli chcemy, aby instrukcja
instr3 była wykonywana "w pętli", nie stawiamy średnika po nawiasie
okrągłym, jak poniżej, chociaż nie jest błąd składniowy.
for(instr1; warunek; instr2) ;
//koniec pętli
instr3;
//instrukcja nie należy do pętli
Również, podobnie jak w przypadku while, jeżeli chcemy, aby zamiast
pojedynczej instrukcji instr3, był wykonywany ciąg instrukcji, należe je
umieścić w bloku.
for(instr1; warunek; instr2)
{
instr3_1;
...
instr3_n;
}
Instrukcje instr1 i instr2 nie muszą być pojedynczą instrukcją. Może być
ich kilka, wtedy poszczególne instrukcje oddzielone są przecinkiem, np.:
for (j=1, i = 2 ; i<5; i++, j++)
Console.WriteLine("{0} + {1} = {2}",i, j , i+j);
Po wykonaniu powyższego fragmentu kodu na ekranie pojawi się:
2 + 1 = 3
3 + 2 = 5
4 + 3 = 7
Instrukcje instr1 i instr2 oraz wyrażenie warunek nie muszą wcale
wystąpić. Dowolny z wymienionych elementów można opuścić, zachowując
jednak średnik oddzielający go od sąsiada:
for( ; ;)
{
...
}
Opuszczenie wyrażenia warunek traktowane jest tak, jakby stała tam wartość
true
. Prowadzi to do powstania pętli nieskończonej, z której można wyjść za
pomocą instrukcji skoku. Instrukcje skoku zostaną omówione w następnym
module tego kursu.
Każdą pętle for możemy zastąpić pętlą while i na odwrót. Przyjmuje się,
chociaż nie jest to bardzo rygorystycznie przestrzegane, że pętlę for
stosujemy, gdy od początku wiadomo, ile razy mają zostać wykonane instrukcje
pętli. Najczęściej pętla for ma następującą postać:
for(int i = 0; i < liczba; i++)
{
//instrukcje pętli
}
Powyższy kod można również zapisać przy pomocy instrukcji while w
następujący sposób:
int i = 0;
//inicjalizacja pętli
while(i < liczba)
{
...//instrukcje pętli
...i++;
//instrukcja kroku
}
Pętla do ... while
Pętla do...while różni się od instrukcji iteracyjny omawianych wcześniej
tym, że warunek jest sprawdzany dopiero po wykonaniu instrukcji pętli. Ma
ona następującą postać:
do
{
//instrukcje pętli
}
while(warunek);
Działanie pętli jest następujące. Najpierw wykonywane są instrukcje pętli. Po
ich wykonaniu sprawdzane jest wyrażenie logiczne warunek. Jeżeli ma
wartość true instrukcje pętli zostają wykonane ponownie. Jeżeli wyrażenie
warunek ma wartość false wykonywanie pętli zostaje przerwane. W
przypadku pętli do...while mamy pewność, że instrukcje pętli zostaną
wykonane co najmniej raz.
Pytania sprawdzające
1.
Napisz fragment kodu, który wypisuje na ekranie sto razy "C# jest łatwy".
Odp.
for(int i = 0; i < 100; i++)
{
Console.WriteLine("C# jest łatwy");
}
2.
Popraw błędy logiczne w poniższym kodzie, obliczającym sumę pierwszy
dziesięciu liczb naturalnych:
suma = 0;
for(int i = 1; i >= 10; i++) ;
suma += i;
Odp.
suma = 0;
for(int i = 1; i <= 10; i++) //;
suma += i;
3.
Zapisz poniższy kod, zapisany przy pomocy pętli for, przy pomocy pętli
while.
for(int i = 1; i <= 100; i+=2)
Console.Write("{0}, ",i);
Odp.
int i = 1;
while(i <= 100)
{
Console.Write("{0}, ",i);
i += 2;
}
4.
Popraw błąd w poniższym kodzie:
...
while(x = 1){ ... }
Odp.
...
while(x == 1){ ... .}
Laboratorium
Ćwiczenie 1:
Napisz program, który znajduje największy wspólny dzielnik (NWD) dwóch
liczb naturalnych. Problemu ten rozwiązuje algorytm Euklidesa. Nie wymaga
on rozkładania liczb na czynniki pierwsze. Co ciekawe algorytmu nie wymyślił
Euklides, a Eudoksos z Knidos – grecki filozof i matematyk. Euklides jedynie
algorytm ten zawarł w swoim dziele Elementy. Data powstania algorytmu
około 300 lat p.n.e.
Start
Wybierz dwie liczby
naturalne n, m
Od większej odejmij mniejszą
roznica = |n-m|
Czy różnica
jest równa zero
n jest szukanym
NWD
Podstaw różnicę za
większą z liczb m, n
Stop
T
N
1. Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
2. Utwórz nowy projekt
a. Z menu File wybierz New/Project...
b. W oknie dialogowym New Project określ następujące właściwości:
i. typu projektu: Visual C#/Windows
ii. szablon: Console Application
iii. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
iv. nazwa projektu: NWD.
v. nazwa rozwiązania: Lab4
3. Wewnątrz metody Main napisz następujący kod:
a. Zadeklaruj trzy zmienne całkowite m, n roznica:
ulong m, n , roznica;
b. Pobierz od użytkownika wartości zmiennych m i n:
...
Console.Write("Podaj wartość m: ");
m = Convert.ToUInt64(Console.ReadLine());
Console.Write("Podaj wartość n: ");
n = Convert.ToUInt64(Console.ReadLine());
c.
Wykonuj póki wartość zmiennej roznica będzie różna od zera
następujące polecenia.
Od większej liczby odejmij mniejszą, wynik podstaw do zmiennej
różnica. Do większej liczby z m i n podstaw wartość zmiennej
roznica.
do
{
roznica = m > n ? m - n: n - m;
if(n>m)
n = roznica;
else
m= roznica;
}
while(roznica != 0);
d. Wypisz na ekranie, że szukanym największym wspólnym dzielnikiem
jest wartość zmiennej n. Zatrzymaj program, aby użytkownik mógł
obejrzeć wyniki.
Console.WriteLine("Największy wspólny dzielnik
¬podanych liczb to {0}.", n);
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 2
Utwórz programu, który oblicza przybliżoną wartość pierwiastka
kwadratowego, dla dowolnie wybranej liczby nieujemnej. Program będzie
działał według poniższego schematu blokowego
1. Dodaj do bieżącego rozwiązania nowy projekt
a. Z menu File wybierz Add/New Project...
b. W oknie dialogowym Add New Project określ następujące
właściwości:
i.
typu projektu: Visual C#/Windows
ii.
szablon: Console Application
iii.
nazwa projektu: Pierwiastek.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt Pierwiastek w okienku Solution Explorer i z menu
kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
1. Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
2. Utwórz nowy projekt
a. Z menu File wybierz New/Project...
b. W oknie dialogowym New Project określ następujące właściwości:
i. typu projektu: Visual C#/Windows
ii. szablon: Console Application
iii. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
Start
Wybierz liczbę nieujemną a
Podstaw za x liczbę 1 (x=1)
Oblicz x według wzoru:
)
(
2
1
x
a
x
x
Czy x
2
jest
wystarczająco
blisko a
x jest szukanym
pierwiastkiem
Stop
T
N
iv. nazwa projektu: Pierwiastek.
v. nazwa rozwiązania: Lab4
3. Wewnątrz metody Main napisz następujący kod:
a. Zdefiniuj maksymalny dopuszczalny błąd:
const double epsilon = 0.00001;
b. Zadeklaruj dwie zmienne rzeczywiste a, x.. Nadaj zmiennej x wartość
1.
double a, x = 1;
c. Pobierz od użytkownika wartość zmiennej a. Gdy wartość zmiennej a
jest ujemna zgłoś wyjątek.
Console.Write("Podaj wartość zmiennej a: ");
a = Convert.ToDouble(Console.ReadLine());
if(a < 0)
throw new Exception("a nie może być ujemne");
d. Póki odległość między x
2
i a jest większa od epsilon, do zmiennej x
podstawiaj wartość wyrażenia:
while(Math.Abs(x * x - a) > epsilon)
{
x= (x + a / x) / 2;
}
Metoda Math.Abs oblicza wartość bezwzględną liczby.
e. Wypisz na ekranie, że szukanym pierwiastkiem liczby jest wartość
zmiennej x Zatrzymaj program, aby użytkownik mógł obejrzeć wyniki.
Console.WriteLine("Wartością (przybliżoną)
¬pierwiastka kwadratowego liczby {0} jest {1}."
¬,a, x);
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 3
Napisz program obliczający sumę i iloczyn n pierwszych liczb naturalnych
podzielnych przez k, gdzie k oraz n są dowolnymi liczbami naturalnymi.
1. Dodaj do bieżącego rozwiązania nowy projekt
a. Z menu File wybierz Add/New Project...
)
(
2
1
x
a
x
x
ik
a
gdzie
a
iloczyn
i
n
i
i
1
ik
a
gdzie
a
suma
i
n
i
i
1
b. W oknie dialogowym Add New Project określ następujące
właściwości:
i.
typu projektu: Visual C#/Windows
ii.
szablon: Console Application
iii.
nazwa projektu: SumaIloczyn.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt SumaIloczyn w okienku Solution Explorer i z menu
kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
1. Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
2. Utwórz nowy projekt
a. Z menu File wybierz New/Project...
b. W oknie dialogowym New Project określ następujące właściwości:
i. typu projektu: Visual C#/Windows
ii. szablon: Console Application
iii. lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
iv. nazwa projektu: SumaIloczyn.
v. nazwa rozwiązania: Lab4
3. Wewnątrz metody Main napisz następujący kod:
a. Zadeklaruj cztery zmienne całkowite nieujemne n, k, a, iloczyn oraz
suma. Zmiennej suma nadaj wartość 0, zmiennej iloczyn wartość
1. Zmienna a będzie przechowywać aktualną wartość składnika
(czynnika). Wartość 0 jest elementem neutralnym działania dodawanie,
wartość 1 jest elementem neutralnym działania mnożenie.
ulong iloczyn = 1, suma = 0;
ushort a, k, n;
b. Pobierz od użytkownika wartości zmiennych k i n:
Console.Write("Podaj wartość zmiennej n: ");
n = Convert.ToUInt16(Console.ReadLine());
Console.Write("Podaj wartość zmiennej k: ");
k = Convert.ToUInt16(Console.ReadLine());
c.
Podstaw wartość zmiennej k do zmiennej a.
a = k;
d. Wykonaj n razy następujące polecenia
i. Wartość zmiennej suma zwiększ o wartość zmiennej a.
ii. Wartość zmiennej iloczyn zwiększ a razy. Zapewnij, że w razie
przepełnienia, zostanie zgłoszony wyjątek.
iii. Do zmiennej a podstaw wartość kolejnej liczby podzielnej przez k.
for(int i = 0; i < n; i++)
{
suma += a;
checked
{
iloczyn *= a;
}
a += k;
}
e. Wypisz wartości zmiennych suma i iloczyn, a następnie zatrzymaj
program, aby użytkownik mógł obejrzeć wyniki.
Console.Write(" suma = {0}" , suma);
Console.Write(" iloczyn = {0}" , iloczyn);
Console.ReadKey();
4. Skompiluj i uruchom program.
Ćwiczenie 4
Napisz program, grę - zgadnij liczbę. Użytkownik ma zgadnąć liczbę
wylosowaną przez komputer. Do wylosowania liczby pseudolosowej stosuj
następujący kod.
Random generator = new Random();
int liczba = generator.Next(a, b +1);
Do zmiennej liczba zostanie podstawiona wylosowana wartość całkowita z
przedziału <a; b>.
1. Dodaj do bieżącego rozwiązania nowy projekt
a. Z menu File wybierz Add/New Project...
b. W oknie dialogowym Add New Project określ następujące
właściwości:
i. typu projektu: Visual C#/Windows
ii. szablon: Console Application
iii. nazwa projektu: Gra.
2. Uczyń nowo utworzony projekt projektem startowym
a. Zaznacz projekt Gra w okienku Solution Explorer i z menu
kontekstowego wybierz Set as StartUp Project.
albo, gdy rozpoczynasz laboratorium od tego ćwiczenia
1. Uruchom Visual Studio
Naciśnij przycisk Start systemu Windows, wybierz Wszystkie Programy
następnie Microsoft Visual Studio 2005/ Microsoft Visual Studio 2005.
2. Utwórz nowy projekt
a. Z menu File wybierz New/Project...
b. W oknie dialogowym New Project określ następujące właściwości:
i. typu projektu: Visual C#/Windows
ii.
szablon: Console Application
iii.
lokalizacja: Moje Dokumenty\Visual Studio 2005\Projects\
iv.
nazwa projektu: Gra.
v.
nazwa rozwiązania: Lab4
3. Wewnątrz metody Main napisz następujący kod:
a. Zdefiniuj początek i koniec przedziału z którego będą generowane
liczby.
const int a = 0;
const int b = 200;
b. Zadeklaruj następujące zmienne całkowite: n i m. n - liczba
wygenerowana przez generator liczb pseudolosowych; m - liczba
podana przez użytkownika
int n, m;
c.
Wylosuj wartość zmiennej n.
Random generator = new Random();
n = generator.Next(a, b +1);
d. Wykonuj następujące instrukcje, póki użytkownik nie zgadnie
wylosowanej wartości:
i. Pobierz wartość zmiennej m od użytkownika.
ii. Poinformuj użytkownika, czy podana przez niego liczba jest za
duża albo za mała.
do
{
Console.WriteLine("Podaj wartość
¬wylosowanej liczby. Wartość jest z
¬przedziału <{0}, {1}>: ", a, b);
m = Convert.ToInt32(Console.ReadLine());
if(m < n)
Console.WriteLine("Wartość podana jest
¬za mała");
if(m > n)
Console.WriteLine("Wartość podana jest
¬za duża");
}
while(m != n);
e. Pogratuluj użytkownikowi zgadnięcia wylosowanej liczby. Zatrzymaj
program, aby użytkownik mógł obejrzeć wyniki.
Console.WriteLine("Gratulacje!!! Odgadłeś
¬liczbę.");
Console.ReadKey();
4. Skompiluj i uruchom program.