Laboratorium 2. Instrukcje warunkowe

Przed zajęciami laboratoryjnymi zapoznaj się z następującymi pozycjami literatury:

1. Wykład z przedmiotu „Podstawy programowania”

2. J. Grębosz „Symfonia C++” tom 1. ,Oficyna Kallimach, Kraków, 1999

Rozdziały: 1, 2.1, 2.2, 2.6, 2.7, 2.8, 3.1 - 3.4, 4.1, 4.2, 4.5, 4.6, 4.10, 4.11

Przygotowując się do laboratorium przeanalizuj podane poniżej przykłady, odpowiedz na pytania, rozwiąż testy i napisz odpowiednie programy. Po zajęciach zrób zadania podane w ostatnim punkcie tego

opracowania.

Przykłady i pytania

1. Instrukcje if (…) oraz if (…) else. Wyrażenia logiczne

Przykład L2_F0_P1 Przeanalizuj program i odpowiedz na pytania

// L2_F0_P1.cpp Instrukcje warunkowe if-else, if

#include <iostream>

#include <iomanip>

#include <cmath>

using namespace std;

int main()

{

float a, b;

bool war;

cout << setiosflags(ios::fixed); // ustawienie formatu wyjściowego liczb zmiennoprzecinkowych

// zamiast fixed może być np. scientific

cout.precision(5); // 5 cyfr po przecinku

cout << "Podaj pierwsza liczbe: "; cin >> a;

cout << "Podaj druga liczbe: "; cin >> b;

//---Instrukcja (A)

if (a != b)

cout << a << " jest rozne od " << b << endl;

else

cout << a << " jest rowne " << b << endl;

//--- Instrukcja (B)

if ( !(b+2)) cout << b << " jest rowne " << -2 << endl;

//--- Instrukcja (C)

if ( !( a && b) ) cout << "Co najmniej jedna z liczb jest rowna " << 0 << endl;

//--- Instrukcja (D)

war = ( a > -10 and a < 10 ) and ( b > -10 and b < 10 );

if ( not war ) cout << "Co najmniej jedna z liczb jest spoza przedzialu [-10, 10]" << endl;

//--- Instrukcja (E)

if ( (a <-1 || a >1) || a == 0)

cout << "Dla a = " << a << " funkcja y jest nieokreslona" << endl;

else

cout << "Dla a = " << a << " wartosc funkcji y(a) = " << asin(a) + 1/a + sin(a) << endl;

//----------------------------

system("PAUSE");

return 0;

}

S t r o n a | 1 WETI Politechnika Gdańska, POP v.1.4.1

Pytania

Sprawdź czy dla podanych poniżej danych program działa z zgodnie z twoimi przewidywaniami:

1) a = 0, b = -2 2) a = 0.5, b = -11.1

a) Co wypiszą na ekranie instrukcje (B), (C) oraz (D) dla a = 1 i b = 1 ?

b) Co wypisze instrukcja (E), gdy na wejście podamy a = 0 albo a = 3.14 i pominiemy dwie pierwsze linie tej instrukcji? Czy instrukcje warunkowe są konieczne podczas stosowania niektórych funkcji

z biblioteki cmath ? Jeżeli tak, to do czego?

c) Jak zmienić warunki w instrukcjach (A), (B) i (C), aby otrzymać warunki równoważne bez użycia operatorów negacji ( ! , not) ?

d) Jak zmienić warunek w instrukcji (D), aby otrzymać warunek równoważny bez użycia operatorów

koniunkcji ( && , and) ?

e) Jak zmienić warunek w instrukcji (D), aby otrzymać warunek równoważny bez użycia operatorów

alternatywy ( || , or) ?

Odpowiedzi

a) Nic.

b) Błędne wyniki typu 1.#INF , wskazujące na przekroczeniu w dostępnych zakresów liczb. Tak. Przed

użyciem funkcji trzeba mieć pewność, że podane na wejściu funkcji argumenty są poprawne (należą

do dopuszczalnego zakresu i mają odpowiedni typ).

c) Instrukcja (A): if ( a < b || a > b ) ...

Instrukcja (B): if ( ( b + 2 ) == 0 ) ...

Instrukcja (C): if ( a == 0 || b == 0 ) ...

d) Instrukcja (D): war = (( a <= -10 or a >= 10) or ( b <= -10 or b >= 10)); if (war)...

e) Instrukcja (E): if ( !(a >= -1 && a <= 1 && a != 0 ) )...

2. Zagnieżdżone instrukcje if (…) oraz if (…) else

Przykład L2_F0_P2 Przeanalizuj program i odpowiedz na pytania

// L2_F0_P2.cpp Zagniezdzone instrukcje warunkowe if-else, if

#include <iostream>

using namespace std;

int main()

{

int x, y, z;

//-------------------------------------------------------------------------------------

cout << "Podaj liczbe calkowita x: "; cin >> x; // Linia 1

cout << "Podaj liczbe calkowita y: "; cin >> y; // Linia 2

cout << "Podaj liczbe calkowita z: "; cin >> z; // Linia 3

if ( x > y) // Linia 4

if (y <= z); // Linia 5

else cout << "Wniosek : " << " # " <<endl; // Linia 6

//---------------------------------------------------------------------------------------

system("PAUSE");

return 0;

}

S t r o n a | 2 WETI Politechnika Gdańska, POP v.1.4.1

Pytania

a) Do której instrukcji if odnosi się else ? Co oznacza średnik w Linii 5 ?

b) Które z poniższych zdań można wstawić w miejsce znaku #, aby wypisany wniosek był prawdziwy?

1) x jest mniejsze lub równe y

2) y jest większe niż z

3) z to liczba najmniejsza spośród 3 liczb x, y, z

c) Zapisz instrukcje ( Linie 4-6 ) używając dwóch zagnieżdżonych instrukcji if (bez słowa else).

d) Zapisz instrukcje ( Linie 4-6 ) za pomocą jednej instrukcji if ( bez słowa else).

e) Zmień Linię 5, aby zdanie: Nieprawda, że x jest większe od y, zastępujące znak # było prawdziwe?

Odpowiedzi

a) Do instrukcji w Linii 5. Średnik oznacza instrukcję pustą, która nic nie robi.

b) Zdanie 2) albo 3).

c) if ( x > y ) if ( y > z ) cout << "Wniosek : " << " # " << endl; d) if ( x > y and y > z ) cout << "Wniosek : " << " # " << endl;

e) Ujmij Linię 5 w nawiasy klamrowe { if (y <= z); }, wówczas else odnosi się do if w Linii 4.

3. Instrukcja switch

Przykład L2_F0_P3 Przeanalizuj program i odpowiedz na pytania

// L2_F0_P3.cpp Instrukcja warunkowa switch() i instrukcja break

/* Program określa stan gleby na podstawie pomiaru wilgotności [%] */

/* Kryteria: 0.. 9 % - pustynia */

/* 10.. 19 % - gleba bardzo sucha */

/* 20.. 39 % - gleba sucha */

/* 40.. 69 % - gleba właściwa */

/* 70.. 89 % - gleba mokra */

/* 90.. 99 % - bagno */

#include <iostream>

using namespace std;

int main ()

{

int wg;

cout << "Podaj wilgotnosc gleby (0 <= wg <= 99): ";

cin >> wg;

if (wg >= 0)wg = wg/10;

cout << "Stan gruntu : ";

switch (wg){

case 0 : { cout << "pustynia " << endl; break;}

case 1 : { cout << "gleba bardzo sucha " << endl; break;}

case 2 :

case 3 : { cout << "gleba sucha " << endl; break;}

case 4 :

case 5 :

case 6 : { cout << "gleba wlasciwa " << endl; break;}

case 7 :

case 8 : { cout << "gleba mokra " << endl; break;}

case 9 : { cout << "bagno " << endl; break;}

default: { cout << "niepoprawne dane " << endl; break;}

}

system("PAUSE");

return 0;

}

S t r o n a | 3 WETI Politechnika Gdańska, POP v.1.4.1

Pytania

a) Co wypisze na ekranie program dla wg = 77 ?, a gdy usuniemy linię case 7: ?

b) A gdy dodatkowo usuniemy linię z etykietą default ?

c) Co wypisze na ekranie program dla wg = 7, gdy usuniemy pierwszą instrukcję break ?

d) Podaj przykłady typów, które są dopuszczalne oraz takich, które są niedopuszczalne dla wyrażenie w instrukcji switch( wyrażenie).

e) Napisz równoważny program bez użycia instrukcji switch.

Odpowiedzi

a) Stan gruntu: gleba mokra ( z linią case 7:)

Stan gruntu: niepoprawne dane ( bez case 7:)

b) Stan gruntu:

c) Stan gruntu: pustynia

gleba bardzo sucha

d) Dopuszczalne typy całkowitoliczbowe ( np. int, long int, char, bool), niedopuszczalne typy zmiennoprzecinkowe (np. float, double)

e) Możesz zastosować konstrukcję else-if, na przykład:

int main ()

{

int wg;

cout << "Podaj wilgotnosc gleby (0 <= wg <= 99): ";

cin >> wg;

cout << "Stan gruntu: " ;

if (wg < 0) cout << "niepoprawne dane " << endl;

else if (wg < 10) cout << "pustynia " << endl;

else if (wg < 20) cout << "gleba bardzo sucha " << endl;

else if (wg < 40) cout << "gleba sucha " << endl;

else if (wg < 70) cout << "gleba wlasciwa " << endl;

else if (wg < 90) cout << "gleba mokra " << endl;

else if (wg <100) cout << "bagno " << endl;

else cout << "niepoprawne dane " << endl;

system("PAUSE");

return 0;

}

Testy

1. Które instrukcje, bez względu na wartość k oraz a, nigdy nie zostaną wykonane ?

a) if ( k < a and k > a ) instrukcja_1;

else instrukcja_2;

b) if ( k < a ) {

instrukcja_1;

if ( k > b && b > a ) instrukcja_2;

else instrukcja_3;

}

else instrukcja_3;

c) if ( k < a or k > a ) {

instrukcja_1;

if ( a != k ) instrukcja_2;

else instrukcja_3;

}

else if ( k == a ) instrukcja_4;

S t r o n a | 4 WETI Politechnika Gdańska, POP v.1.4.1

2. Przy jakich wartościach k wykona się wykona sie jedna z instrukcji oznaczonych jako instrukcja_1 ?

int main()

{

int k;

cin >> k;

switch ( k + 2 ) {

case 1:

case 2: if ( k == -1 ) instrukcja2;

else instrukcja_1;

break;

case 3: if (k > 2) instrukcja_1;

else instrukcja_3;

break;

default: instrukcja_1;

break;

system("PAUSE");

return 0;

}

3. Wskaż fragmenty, które kompilator programu uzna za błędne:

a) if(k)

if(k)

if(k);

else k = k - 1;

b) if(k);

else k = k - 1;

else k = k - 1;

c) if(k);

else if(!k) k = k - 1;

d) if(k) k = k - 1;

else;

e) if(1)

else k = k - 1;

4. Zapisz instrukcje if-else w postaci wyrażenia warunkowego:

(warunek) ? wartosc_1 : wartosc_2

a) float liczba;

if( liczba < 0 ) liczba = - liczba;

else liczba = liczba;

b) float x, y;

if( x > 1 ) y = x-1;

else y = x*x -1;

Odpowiedzi

Test 1: a) instrukcja_1, b) instrukcja_2, c) instrukcja_3

Test 2: k ≠ -1 i k ≠ 1

Test 3: b) oraz e)

Test 4: a) liczba = (liczba < 0) ? ( –liczba ) : ( liczba );

b) y = ( x > 1 ) ? ( x – 1 ) : ( x * x – 1 );

S t r o n a | 5 WETI Politechnika Gdańska, POP v.1.4.1

Zadania przygotowujące do laboratorium

Zapoznaj się z treścią zadania, przemyśl rozwiązanie a następnie napisz, uruchom i przetestuj programy.

Zadanie L2_F0_Z1

Napisz program, który dla podanej liczby całkowitej wypisuje na ekranie komunikat:

• „Fizz”, jeżeli liczba jest podzielna przez 3, ale nie przez 5;

• „Buzz”, jeżeli liczba jest podzielna przez 5, ale nie przez 3;

• „FizzBuzz”, jeżeli liczba jest podzielna przez 15;

• Wartość podanej liczby, jeżeli nie jest ona podzielna ani przez 3, ani przez 5.

Zastosuj konstukcję else-if. Zastanów się nad kolejnością sprawdzania warunków.

// L2_F0_Z1.cpp Podzielnosc przez 3, 5 i 15

#include <iostream>

using namespace std;

int main()

{

int i;

cout << "Podaj liczbe calkowita: "; cin >> i;

cout << "Wynik analizy: " << endl;

if( i % 15 == 0 ) cout << "FizzBuzz" << endl; // Ten warunek musi być pierwszy. Dlaczego?

else if ( i % 3 == 0 ) cout << "Fizz" << endl; // i%3 = reszta z dzielenia zmiennej i przez 3

else if ( i % 5 == 0 ) cout << "Buzz" << endl;

else cout << i << endl;

system("PAUSE");

return 0;

}

Zadanie L2_F0_Z2

Napisz program, który wczytuje 3 różne liczby rzeczywiste: a, b oraz c i sprawdza, czy c zawiera się w przedziale ( a, b), gdy a < b, albo w przedziale ( b, a), gdy a > b.

a) Uzupełnij poniższy szkielet L2_F0_S2, aby program działał poprawnie.

b) Napisz program krócej, zachowując ten sam układ instrukcji if-else oraz nie stosując w warunkach operatorów logicznych: not, or, and ( ! , || , && ).

// L2_F0_S2.cpp

#include <iostream>

using namespace std;

int main()

{

double a, b, c;

cout << "Podaj 3 rozne liczby rzeczywiste: a b c : "; cin >> a >> b >> c;

cout << endl << "Czy liczba c zawiera sie w przedziale (a,b) lub (b,a)\? ";

//----------------------------------------------------------- UZUPELNIJ

if( a < b )

if ( ) cout << "TAK " << endl;

else cout << "NIE " << endl;

else

if ( ) cout << << endl;

else cout << << endl;

//------------------------------------------------------------

system ("PAUSE");

return 0;

}

S t r o n a | 6 WETI Politechnika Gdańska, POP v.1.4.1

Rozwiązanie a)

// L2_F0_Z2a.cpp

#include <iostream>

using namespace std;

int main()

{ double a, b, c;

cout << "Podaj 3 rozne liczby rzeczywiste: a b c "; cin >> a >> b >> c;

cout << endl << "Czy liczba c zawiera sie w przedziale (a,b) lub (b,a)\? ";

//---------------------------------------------------------------

if( a < b )

if ( c > a && c < b) cout << "TAK " << endl;

else cout << "NIE " << endl;

else

if ( c > b && c < a) cout << "TAK " << endl;

else cout << "NIE " << endl;

//---------------------------------------------------------------

system ("PAUSE");

return 0;

}

Rozwiązanie b)

// L2_F0_Z2b.cpp

#include <iostream>

using namespace std;

int main()

{ double a, b, c;

cout << "Podaj 3 rozne liczby rzeczywiste: a b c "; cin >> a >> b >> c;

cout << endl << "Czy liczba c zawiera sie w przedziale (a,b) lub (b,a)\? ";

//---------------------------------------------------------------

if( c > a )

if ( c < b) cout << "TAK " << endl;

else cout << "NIE " << endl;

else

if ( c > b) cout << "TAK " << endl;

else cout << "NIE " << endl;

//---------------------------------------------------------------

system ("PAUSE");

return 0;

}

Zadanie L2_F0_Z3

Program wczytuje współczynniki a, b, c równania kwadratowego ax 2 + bx + c = 0. Jeżeli a ≠ 0, to oblicza ile rozwiązań rzeczywistych ma równanie kwadratowe, w przeciwnym przypadku wpisuje komunikat: „To nie

jest równanie kwadratowe”.

// L2_F0_Z3.cpp Sprawdzenie ile rozwiazan ma rownanie kwadratowe

#include <iostream>

using namespace std;

int main()

{

double a, b, c;

cout << "Podaj 3 liczby rzeczywiste: a b c : "; cin >> a >> b >> c;

if( a != 0 ) {

cout << endl << "Rownanie kwadratowe a*x*x + b*x + c = 0";

if ( b*b - 4*a*c > 0 ) cout << " ma 2 rozwiazania rzeczywiste" << endl;

else if ( b*b - 4*a*c < 0 ) cout << " nie ma rozwiazan rzeczywistych" << endl;

else cout << " ma 1 rozwiazanie rzeczywiste" << endl;

}

else

cout << "To nie jest rownanie kwadratowe" << endl;

system ("PAUSE");

return 0;

}

S t r o n a | 7 WETI Politechnika Gdańska, POP v.1.4.1

Zadanie L2_F0_Z4

Program wczytuje trzy liczby rzeczywiste a, b, c i sprawdza czy mogą być bokami trójkąta. Jeżeli tak, to wypisuje na ekranie słowo TAK, jeżeli nie – słowo NIE. Sprawdź działanie swojego programu dla różnych danych wejściowych. W szczególności uwzględnij dane, dla których długość jednego z boków „znacząco”

różni się od pozostałych, np. a = b = 1e10, c = 1e-10. Czy zawsze otrzymujemy poprawny wynik? Jeżeli nie, to zastanów się dlaczego.

Wskazówka: suma długości dowolnych dwóch boków trójkąta jest większa niż długość trzeciego boku.

// L2_F0_Z4.cpp Czy a b c moga tworzyc trojkat?

#include <iostream>

using namespace std;

int main()

{

double a, b, c;

cout << "Podaj 3 liczby rzeczywiste: a b c : "; cin >> a >> b >> c;

cout << endl << "Czy liczby moga byc bokami trojkata\? ";

if ( b+c > a && a+c > b && a+b > c ) cout << "TAK " << endl;

else cout << "NIE " << endl;

system ("PAUSE");

return 0;

}

Zadania do samodzielnego rozwiązania po laboratorium

L2_F3_Z1

Napisz program, który wczytuje trzy różne liczby rzeczywiste a, b, c i sprawdza, która z nich jest najmniejsza, a która największa. Dwie liczby będziemy uważali za równe, gdy ich różnica jest większa niż 1e-9. Napisz program tak aby w najgorszym przypadku wykonał trzy porównania. Wynik przedstaw w postaci

wykładniczej dokładnością do 4 cyfr po przecinku.

Przykład:

Dla liczb (2.53e-1, -35.7, -1) program wypisze na ekranie:

Liczba najwieksza = 2.530e-1

Liczba najmniejsza = -3.570e1

L2_F3_Z2

Napisz program, który wczytuje dwie współrzędne punktu P( x, y) i sprawdza czy punkt należy do koła o promieniu r=2 i środku (0, 0) i jednocześnie zawiera się w I albo II ćwiartce układu współrzędnych (przyjmij, że nieujemne części osi OX oraz OY należą do I ćwiartki, a ujemna część osi OX do II).

S t r o n a | 8 WETI Politechnika Gdańska, POP v.1.4.1

L2_F3_Z3

Napisz program, który wyznacza rozwiązania rzeczywiste równania

2

ax + bx + c = 0

na podstawie wczytanych 3 liczb rzeczywistych a, b, c.

Jeżeli a = 0, to program powinien rozwiązać równanie liniowe a w przeciwnym razie, równanie kwadratowe.

Wyniki wyprowadzić w formacie wykładniczym z dokładnością 5 cyfr po przecinku. W szczególnych

przypadkach program powinien wypisywać komunikaty informujące, że :

1. Równanie nie ma rozwiązań w zbiorze liczb rzeczywistych

2. Równanie ma nieskończoną liczbę rozwiązań

L2_F3_Z4

Dany jest rosnący ciąg liczb rzeczywistych: p 1, p 2,..., p 7 ( p 1 < p 2 < ... < p 7). Elementy ciągu, nazwane dalej progami, definiują 8 przedziałów:

( −∞, p 1 ) [ p 1, p 2 ) [ p 2, p 3 ) [ p 3, p 4 ) [ p 4, p 5 ) [ p 5, p 6 ) [ p 6, p 7 ) [ p 7, +∞ ) Napisz program kwalifikujący wczytaną liczbę x do jednego z ośmiu przedziałów i wykonujący co najwyżej trzy proste porównania typu if ( x > p i ). Przyjmij, że progi są stałymi liczbowymi (ich wartości ustal samodzielnie). Program powinien wypisywać na standardowym wyjściu przedział (w postaci odpowiednich

nierówności), do którego należy x.

Wskazówka: zauważ, że jeżeli x należy do przedziału ( −∞, p 4 ), to nie należy do żadnego z czterech przedziałów o końcach w [ p 4, +∞ ). Po rozstrzygnięciu przynależności do ( −∞, p 4 ), tą samą obserwację i test względem „środkowego” przedziału możesz teraz zastosować do dwóch części przedziału ( −∞, p 4 ), itd.

Uwaga: poprzednie wersje programu, podane w przykładzie L2_F0_P3 nie były optymalne pod względem ilości wykonywanych porównań (w najgorszym przypadku wymagały siedmiu porównań, aby określić

przynależność do właściwego przedziału). Ich zaletą jest jednak duża czytelność i powinny być stosowane, gdy szybkość działania programu nie jest kryterium nadrzędnym.

S t r o n a | 9 WETI Politechnika Gdańska, POP v.1.4.1