Algorytmika i Programowanie.
Instrukcje sterujące i pętli cd.
Zakład Zastosowań Informatyki
w In\ynierii Lądowej
Wydział In\ynierii Lądowej
Politechnika Warszawska
Sławomir Czarnecki
Porównywanie wartości
" Podejmowanie decyzji wymaga mechanizmu porównywania
wielkości (instrukcji sterujących), które bardzo często
wykorzystują operatory logiczne.
" Mamy 6 podstawowych operatorów logicznych:
< mniejszy ni\
<= mniejszy ni\ lub równy
> większy ni\
>= większy ni\ lub równy
== równy
!= nie równy
Operator porównania ==, ma dwa, umieszczone
obok siebie znaki '='.
Operator przypisania =, ma jeden znak '='.
Częstą pomyłką jest u\ywanie operatora =
przypisania w miejscach, gdzie powinien być
u\yty operator porównania == .
" Ka\dy z tych operatorów porównuje ze sobą dwie wartości i zwraca
jedną z dwóch wartości boolowskich:
true (prawda)
false (fałsz)
" Poni\ej kilka przykładów u\ycia operatorów logicznych.
" Załó\my, \e zmienne całkowite i, j zostały zainicjalizowane
odpowiednio wartościami 10 i -5
" Wtedy wartość boolowska ka\dego z wyra\enia,
i > j
i != j
i > 8
i <= j+15
będzie true.
Instrukcja sterująca if
Podstawowa instrukcja if pozwala na wykonanie pojedynczej
instrukcji lub bloku instrukcji zawartych pomiędzy nawiasami {...}
w przypadku kiedy warunek (condition) ma wartość logiczną true.
int Fix;
cin >> Fix;
if (Fix>0)
cout<<"positive number"<
" Testowany warunek pojawia się w nawiasach ( ) za słowem
kluczowym if.
" Zwróćmy uwagę na poło\enie średnika ; .
int Fix;
cin >> Fix;
if (Fix > 0)
{
cout<<"positive number"<cout<<"Fix = "<}
" W przykładzie, dwie instrukcje w bloku będą wykonane tylko jeśli
wartość logiczna wyra\enia (Fix > 0) będzie true i bez nawiasów {...},
jedynie pierwsza instrukcja wykonałaby się, natomiast druga instrukcja
cout<<"Fix = "<wykonywałaby się zawsze niezale\nie od wartości logicznej
wyra\enia (Fix > 0).
" Zauwa\my, \e średnik pojawia się po ka\dej instrukcji nie pojawia
się natomiast po znaku }, który zamyka blok.
" W bloku mo\e być dowolna liczba instrukcji.
" Jeśli instrukcja if zwróciłaby false, wtedy \adna instrukcja nie będzie
wykonana.
Zagnie\d\anie instrukcji if
" Instrukcją wykonywaną po instrukcji if mo\e być kolejna instrukcja if.
" Taki sposób u\ycia nazywamy zagnie\d\aniem instrukcji if.
" Liczba kolejnych zagnie\d\onych instrukcji if mo\e być dowolna.
double Fix;
cin >> Fix;
if (Fix > 0)
{
if (Fix < 1)
cout<<"number less then 1"<if (Fix > 1)
cout<<"number greater then 1"<cout<<"Fix = "<}
" Jeśli zmienna Fix będzie dodatnia to sterowanie programem będzie
przekazane do bloku { } i w zale\ności od wartości zmiennej Fix
będzie lub nie będzie wyświetlony odpowiedni napis.
" Dla Fix ==1 nie zostanie wyświetlony \aden napis.
" Jeśli natomiast zmienna Fix będzie dodatnia to zawsze będzie
wyświetlona wartość tej zmiennej.
int Fix; Rozszerzona instrukcja if
cin >> Fix; 1 true
if (Fix % 2) 0 false
cout<<"Fix is an odd number"<" Po wczytaniu wartości Fix, sprawdzana jest wartość reszty z dzielenia
tej wartości przez 2 (u\ycie operatora %) jako warunek dla instrukcji if.
" W tym przypadku, wartością wyra\enia pełniącego rolę warunku w
instrukcji if jest typ całkowity a nie logiczny typ bool.
" Nie jest to błąd, poniewa\ instrukcja if interpretuje a ka\dą niezerową
wartość wyra\enia jako prawdę true, a zero interpretowane jest zawsze
jako fałsz false.
" Innymi słowy, w naszym przykładzie, instrukcja if (Fix % 2)
jest równowa\na instrukcji if (Fix % 2 != 0).
" Jeśli resztą będzie 1, to warunek ma wartość logiczną true i kolejną
instrukcją będzie wyświetlenie na ekranie odpowiedniego napisu.
" Jeśli resztą będzie 0, warunek będzie miał wartość logiczną false i nic
nie zostanie wykonane.
Instrukcja if else
" Kombinacja if-else umo\liwia wybór pomiędzy dwoma opcjami.
" Poni\szy schemat ilustruje instrukcję if-else:
" Strzałki na
diagramie
wskazują
sekwencje
wykonania
instrukcji,
w zale\ności
od wartości
logicznej w
instrukcji if
condition
(true lub false)
int Fix;
cin >> Fix;
if (Fix % 2)
cout<<"Fix is an odd number"<else
:&
:&
:&
:&
cout<<"Fix is an even number"<cout<<"Fix = "<" Wykonanie obu kodów jest
int Fix;
identyczne, ale kod w
cin >> Fix;
pierwszym przykładzie jest
if (Fix % 2)
krótszy i przejrzystszy.
{
cout<<"Fix is an odd number"<cout<<"Fix = "<}
else
{
cout<<"Fix is an even number"<cout<<"Fix = "<}
Warunki wielu alternatyw
" Zapis zagnie\d\onej instrukcji if mo\e być uproszczony i zastąpiony
tzw. warunkami wielu alternatyw. Zobaczmy to na przykładzie:
#include
using namespace std;
int main()
{
const double minWarmWorking=30;
const double maxWarmWorking=60;
double temperature;
cout<<"temperature = ";
cin>>temperature;
if (temperature < minWarmWorking)
cout<else
if (temperature <= maxWarmWorking)
cout<else
cout<return 0;
}
#include
using namespace std;
int main()
{
const double minWarmWorking=30;
const double maxWarmWorking=60;
double temperature;
cout<<"temperature = ";
cin>>temperature;
if (temperature < minWarmWorking)
cout<else if (temperature <= maxWarmWorking)
cout<else
cout<return 0;
}
" Taki zapis czyni kod bardziej przejrzysty i zrozumiały. Pojawienie się
kolejnej instrukcji else zdeterminowane jest przez niespełnienie
warunku w instrukcji else bezpośrednio ją poprzedzającej.
" Instrukcje po ostatniej instrukcji else zawsze się wykonają o ile
wszystkie poprzednie warunki przy else if byłyby fałszywe.
const double t0=0;
const double t1=100;
const double t2=1000;
const double t3=1000000;
double temperature;
cout<<"temperature = ";
cin>>temperature;
if (temperature < t0)
cout<else if(temperaturecout<else if(temperaturecout<else if(temperaturecout<else
cout<" Pamiętajmy, \e else jest zawsze związane z ostatnim
poprzedzającym if .
" Wcięcia nie mają w języku C++ \adnego znaczenia !!!
#include #include
using namespace std; using namespace std;
void main() void main()
{ {
double x; double x;
cin>>x; cin>>x;
if (x != 0) if (x != 0)
if (x < 1) if (x < 1)
cout<<1/x<else else
cout<<"x is equal to 0"; cout<<"x is equal to 0"<} }
" Kod obydwu powy\szych przykładów jest identyczny.
" Brak wcięcia przy instrukcji else w pierwszym kodzie nie wpływa
na pierwszą instrukcję if, np. dla x = 2.5 otrzymamy (chyba ?)
niespodziewany napis: x is equal to 0.
" Wynika to z faktu, \e oba kody są równowa\ne następującemu
kodowi:
#include
using namespace std;
void main()
{
double x;
cin>>x;
if (x != 0)
{
if (x < 1)
cout<<1/x<else
cout<<"x is equal to 0"<z pewnością, nie było naszą
}
intencją pisać nonsens!
}
" Aby poprawnie zapisać kod, musimy w tej sytuacji dodać nawiasy
{...}, co pokazano na poni\szym (poprawionym) przykładzie:
#include
using namespace std;
void main()
{
double x;
cin>>x;
if (x != 0)
{ Dodatkowe nawiasy {...} są potrzebne
if (x < 1)
cout<<1/x<}
Dodatkowe nawiasy {...} są potrzebne
else
cout<<"x is equal to 0"<teraz ma to sens !
}
Operatory logiczne w wyra\eniach
" U\ywanie instrukcji if, if-else, w której mamy więcej ni\ dwa warunki,
mo\e być czasami mało przejrzyste (tym mniej przejrzyste im więcej
mamy warunków)
" Operatory logiczne w znacznym stopniu mogą poprawić czytelność
kodu a tym samym zmniejszyć prawdopodobieństwo pomyłki.
" Dysponujemy trzema operatorami logicznymi:
&& logiczna koniunkcja AND
|| logiczna alternatywa OR
! logiczna negacja (NOT)
Tablica logiczna dla operatora &&
(matematycznie: '" )
Tablica logiczna dla operatora ||
(matematycznie : (" )
ę! Tabela logiczna dla implikacji: p ! q
ę!
ę!
ę!
Pamiętamy, \e: (p ! q) ! (~p (" q)
#include
using namespace std;
void main()
{
" W tym przykładzie, zaczynamy od
double x,y;
wczytania dwóch liczb x i y.
cin>>x;
cin>>y;
if(((x >= 0) && (x <= 1)) || ((y >= 0) && (y <= 1)))
cout<<"Bingo";
else
cout<<"Try again";
}
" Warunek if składa się z dwóch wyra\eń logicznych połączonych
operatorem || (OR), a zatem, jeśli którekolwiek z nich będzie miało
wartość logiczną true, wtedy wartość logiczna całego warunku w if
będzie równa true i napis Bingo zostanie wyświetlony.
" Jeśli wartość logiczna obydwu wyra\eń będzie false, wtedy instrukcja
else będzie uruchomiona i napis Try again zostanie wyświetlony.
Operator warunkowy
" Operator warunkowy mo\na zdefiniować następująco:
condition ? expression1 : expression2
" Jeśli wartość logiczna condition jest true, wtedy wynik ma wartość
wyra\enia expression1,
w przeciwnym przypadku wartość tego operatora ma wartość
wyra\enia expression2.
" Zobaczmy jak działa ten operator na przykładzie.
" Załó\my, \e mamy dwie zmienne, a i b, oraz chcemy większą z
wartości a lub b przypisać trzeciej zmiennej c.
" Mo\emy to elegancko zrobić u\ywając operatora warunkowego:
c = a>b ? a : b; // Przypisuje c maksymalną wartość a lub b
" Pierwszy argument operatora warunkowego jest wyra\eniem
logicznym a>b .
" Jeśli wartość logiczna tego wyra\enia jest true wtedy drugi argument
tego operatora w naszym przypadku a jest wybrany jako wartość
operatora i ta wartość zostanie przypisana zmiennej c.
" Jeśli wartość logiczna tego wyra\enia jest false wtedy trzeci argument
tego operatora w naszym przypadku b jest wybrany jako wartość
operatora i ta wartość zostanie przypisana zmiennej c.
" A zatem wartość całego wyra\enia
a>b ? a : b
będzie a jeśli a będzie większe od b oraz b w przeciwnym przypadku.
" Wartość ta zostanie następnie przypisana zmiennej c
c = a>b ? a : b.
" U\ycie operatora warunkowego w tym przykładzie jest równowa\ne
następującej instrukcji if :
if (a>b)
c = a;
else
c = b;
Przykład u\ycia operatora warunkowego w bardziej
rozbudowanym przykładzie
" Często łączy się u\ycie operatora warunkowego z instrukcją wyjścia
w zale\ności od wartości logicznej wyra\enia, np.
#include
using namespace std;
void main()
{
double x,y;
cin>>x;
cin>>y;
cout<<((((x >= 0) && (x <= 1)) || ((y >= 0) && (y <= 1))) ? "Bingo" : "Try again");
}
= "Bingo" lub "Try again"
Instrukcja switch
" Instrukcja switch umo\liwia nam wybór spośród wielu mo\liwych
przypadków w oparciu o stałą wartość danego wyra\enia innymi
słowy, słu\y do podejmowania wielowariantowych decyzji.
#include
using namespace std;
" Po wczytaniu
void main()
{
wartości zmiennej
int num;
num, instrukcja
cout<switch będzie
<<"Enter integer between [-2,2]: ";
wykonywana
cin>>num;
w zale\ności od tej
switch(num)
{
wartości.
case -2:
case -1: cout<break;
case 0: cout<break;
case 1:
case 2: cout<break;
default: cout<}
}
#include " Jeśli wartość
using namespace std;
wyra\enia num
void main()
odpowiada którejś
{
z wartości podanej
int num;
w jednej z etykiet
cout<<<"Enter integer between [-2,2]: "; case wówczas
cin>>num;
wykonywane są
switch(num)
instrukcje
{
począwszy
case -2:
od tej etykiety.
case -1: cout<break; " Wykonanie ich
case 0: cout<kończy się po
break;
napotkaniu instrukcji
case 1:
break.
case 2: cout<" Powoduje to
break;
default: cout<}
switch.
}
" Jeśli wartość
#include
using namespace std;
wyra\enia nie
void main()
zgadza się z \adną
{
z wartości podanych
int num;
przy etykietach case,
cout<wówczas wykonują
<<"Enter integer between [-2,2]: ";
cin>>num;
się instrukcje
switch(num)
umieszczone po
{
etykiecie default.
case -2:
" Etykiety default
case -1: cout<mo\e nie być wcale
break;
case 0: cout<i wtedy jeśli wartość
break;
wyra\enia w
case 1:
nawiasie przy
case 2: cout<słowie kluczowym
break;
switch nie zgadza się
default: cout<}
z \adną z wartości
} przy etykietach case, następuje opuszczenie instr. switch
#include
" Instrukcji
using namespace std;
następujących po
void main()
etykiecie case nie
{
musimy kończyć
int num;
instrukcją break i
cout<<<"Enter integer between [-2,2]: ";
jeśli jej nie
cin>>num;
umieścimy, to
switch(num)
zaczną się
{
wykonywać
case -2:
instrukcje
case -1: cout<break;
umieszczone pod
case 0: cout<następną etykietą
break;
case.
case 1:
case 2: cout<break;
default: cout<}
}
#include
using namespace std;
void main()
{
int num;
cout<<<"Enter integer between [-2,2]: ";
cin>>num;
switch(num)
{
case -2:
case -1: cout<break;
case 0: cout<break;
case 1:
case 2: cout<break;
default: cout<}
}
Instrukcja goto
Instrukcja ta ma formę:
goto etykieta ;
Po napotkaniu takiej instrukcji wykonywanie programu przenosi się
do miejsca gdzie jest dana etykieta
int num;
cout<<"Enter integer: ";
cin>>num;
if((num < -1) || (num > 1))
goto myLabel;
switch(num)
{
case -1:cout<< "Negative number";
" Przykład u\ycia instrukcji
goto myLabel;
umieszczonej w wierszu, w
case 0:cout<< "Zero";
którym jest etykieta.
goto myLabel;
" Etykieta jest to nazwa, po
case 1:cout<< "Positive number";
której następuje dwukropek.
goto myLabel;
}
...
myLabel:cout<<"myLabel executed";
...
" Instrukcja goto jest zawsze mo\liwa do zastąpienia innymi
instrukcjami i zawsze, za wyjątkiem przypadków, kiedy jest to
podyktowane jakimiś specjalnymi względami, powinniśmy
unikać jej stosowania.
Instrukcje pętli
" Mo\liwość wielokrotnego powtarzania grupy instrukcji, ma
fundamentalne znaczenie w niemal wszystkich algorytmach.
" Instrukcja pętli wykonuje ciąg instrukcji dopóty dopóki wartość
logiczna pewnego wyra\enia ma wartość logiczną true (lub false).
" Okazuje się, \e ju\ na tym etapie naszych rozwa\ań jesteśmy
w stanie napisać kod pętli.
" Wszystko czego potrzebujemy to instrukcje if i goto.
n
n n +1 10 10 +1
) ( )
= = 55
"i =1+ 2 +...+ n = (
2 2
i=1
#include " W tym przykładzie, obliczymy sumę
using namespace std; liczb naturalnych od 1 do n = 10.
void main()
{
const int n = 10 ;
int i = 1 , sum = 0 ;
loop :
sum += i ;
if(++i <= n)
goto loop ;
cout<cout<}
" Inicjalizujemy zmienną i
#include
wartością 1, którą następnie
using namespace std;
dodajemy do zmiennej sum,
void main()
którą wcześniej inicjalizujemy
{
zerem (sum jest teraz równe 1).
const int n = 10 ;
" W wyra\eniu warunkowym w
int i = 1 , sum = 0 ;
instrukcji if, i jest najpierw
loop :
inkrementowane, a dopiero
sum += i ;
pózniej sprawdzany jest
if(++i <= n)
warunek czy dodawana liczba
goto loop ;
nie przekroczyła wartości n.
cout<" Dopóty dopóki mamy liczbę i
cout<z dopuszczalnego zakresu,
}
następuje skok do (pustej)
i = 2 i = 4
instrukcji oznaczonej etykietą
10
"i = 1+ 2 + 3 + 4 + ...+10 = 55 = sum loop i w następnej instrukcji
i=1
obliczana jest kolejna suma
i = 1 i = 3 i = 10
częściowa sum,... itd..
" Działanie pętli jest zatem całkiem proste.
" U\ywamy jednak instrukcji goto i wprowadzamy etykietę w
programie, co wcześniej było uznane za zły styl programowania.
" Mo\emy jednak u\yć specjalnej instrukcji pętli for i znacznie uprościć
kod:
#include
" Warunki determinujące
using namespace std;
wykonanie pętli pojawiają się
void main()
w nawiasie po słowie
{
kluczowym for
const int n = 10 ;
" Widzimy tu 3 wyra\enia :
int sum = 0;
- pierwsze inicjalizuje i jedynką.
int i ;
- w drugim sprawdzany jest
for(i=1 ; i <= n ; i++)
warunek, czy i <= n
sum += i ;
- w trzecim zwiększana jest
cout<zmienna i po ka\dej iteracji.
cout<}
" Ogólna definicja pętli for jest następująca:
for (initializing_expression; test_expression; step_expression)
loop_statement;
" Oczywiście, loop_statement mo\e być blokiem
instrukcji pomiędzy nawiasami { }.
" Wyra\enia kontrolujące pętlę for mogą
składać się nawet z kilku instrukcji
oddzielonych zwykłymi przecinkami , .
" W wyra\eniu initializing_expression
inicjalizujemy jedną lub więcej potrzebnych
zmiennych.
" W wyra\eniu test_expression
testujemy warunki dalszego wykonania pętli.
" W wyra\eniu step_expression
inkrementujemy, dekrementujemy lub
przeprowadzamy bardziej skomplikowane
operacje na zmiennych sterujących pętlą.
Instrukcje break i continue
" Dysponujemy ponadto dwoma instrukcjami, które u\yte w pętli, mogą
zmieniać kolejność działań w pętli są to instrukcje : break i continue.
" Program będzie obliczał sumę sum liczb
#include
naturalnych od 1 do n = 10 dopóty dopóki
using namespace std;
void main()
obliczana na bie\ąco wartość zmiennej sum
{
będzie mniejsza od max_sum=30.
const int n=10;
" Jeśli obliczona wartość sum oka\e się większa
const int max_sum=30;
int sum=0;
lub równa max_sum, odtworzona będzie
for(int i=1;i<=n;i++)
poprzednia jej wartość i zostanie u\yta
{
instrukcja break.
sum += i;
if(sum >= max_sum)
" Efekt działania break w pętli jest podobny do
{
działania w instrukcji switch.
sum -= i;
" Następuje natychmiastowe wyjście z instrukcji
break;
}
for, co w naszym przypadku oznacza
}
wyświetlenie wartości zmiennej sum.
cout<}
" Wykonanie w pętli instrukcji continue powoduje zaniechanie
instrukcji będących treścią pętli, jednak w przeciwieństwie do
instrukcji break sama pętla nie zostaje przerwana, continue przerywa
tylko ten obieg pętli i zaczyna następny, kontynuując pracę pętli.
" W tej pętli program będzie obliczał sumę sum
liczb naturalnych od 1 do n = 10 dopóty dopóki
#include
obliczona aktualna wartość sum przekroczy lub
using namespace std;
będzie równa wartości max_sum=30.
void main()
" Spełnienie powy\szego warunku spowoduje
{
const int n=10;
w naszym przykładzie jedynie tzw. puste
const int max_sum=30;
przebiegi pętli a\ do spełnienia warunku jej
int sum=0;
stopu zale\nego od wartości zmiennej i.
for(int i=1;i<=n;i++)
{
" Z tego te\ względu, jest to przy okazji przykład
if(sum >= max_sum)
złego stylu projektowania (oczywiście nie ze
continue;
względu na u\ycie instrukcji continue !)
sum += i;
}
cout<}
Efekt działania instrukcji
break oraz continue w pętli
for został zilustrowany obok.
Instrukcja while
" Drugim rodzajem pętli w C++ jest pętla while.
" O ile pętla for jest przede wszystkim u\ywana w przypadkach kiedy
znana jest z góry liczba pętli do wykonania, to pętlę while
wygodnie jest stosować w przypadkach kiedy jej kontynuacja
(lub zaniechanie) zale\y od wartości pewnego wyra\enia logicznego,
które musi być obliczane i modyfikowane wewnątrz pętli.
" Forma pętli while jest następująca:
while(condition)
loop_statement;
gdzie instrukcje w loop_statement będą sukcesywnie wykonywane
dopóty dopóki wartość logiczna wyra\enia condition będzie true.
" Przerwanie pętli następuje w momencie kiedy wartość logiczna
condition będzie false.
" Działanie pętli while.
f& Największy Wspólny Dzielnik-NWD
(Greatest Common Divisor-GCD) dwóch liczb naturalnych.
Ą% Wersja iteracyjna algorytmu Euklidesa.
ś% Pre: m i n dwie liczby naturalne.
ś% Post: GCD (największy wspólny dzielnik m i n)
Algorytm
1. Zainicjalizuj a wartością m i b wartością n
(a , b) = (m , n)
2. Dopóty dopóki b jest dodatnie 0 (b > 0) przypisz jednocześnie (!)
b do a i resztę z dzielenia a przez b do b
(a , b) = (b , a % b)
3. GCD = a
#include
using namespace std;
void main()
{
long m,n,a,b,c;
long GCD;
cout<<}
Pętla do-while
" Pętla do-while jest podobna do pętli while poniewa\ umo\liwia
wykonanie sekwencji instrukcji dopóty dopóki wartość logiczna
wyra\enia sterującego pętlą pozostaje true.
" Ró\nica polega na tym, \e sprawdzenie wartości logicznej wyra\enia
sterującego pętlą następuje po wykonaniu wszystkich sekwencji
instrukcji a nie na początku pętli jak to jest w przypadku pętli while
lub for.
" Wynika stąd, \e instrukcje w pętli do-while są zawsze wykonane
przynajmniej raz.
" Ogólna postać pętli do-while jest następująca:
do
{
loop_statements;
} while (condition);
" Pętla do-while
Zagnie\d\anie pętli
" Istnieje mo\liwość zagnie\d\ania instrukcji pętli (dowolnej ich liczby).
#include
using namespace std;
void main()
{
int i,j,mult;
const int I=4;
const int J=4;
for(i=1 ; i <= I ; i++)
for(j=1 ; j <= J ; j++)
{
mult = i * j ;
cout<}
cout<}
Wyszukiwarka
Podobne podstrony:
AiP wyklad03
AiP wyklad01
AiP wyklad05
AiP wyklad04
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej
mo3 wykladyJJ
ZARZĄDZANIE WARTOŚCIĄ PRZEDSIĘBIORSTWA Z DNIA 26 MARZEC 2011 WYKŁAD NR 3
Wyklad 2 PNOP 08 9 zaoczne
Wyklad studport 8
Kryptografia wyklad
Budownictwo Ogolne II zaoczne wyklad 13 ppoz
więcej podobnych podstron