Prima pagină > Tutoriale C++ > Capitolul 3: Controlul instructiunilor

Capitolul 3: Controlul instructiunilor


3.1 Operatori relationali, de egalitate si logici

Operatori relationali : <, >, <=, >=
Operatori de egalitate: ==, !=
Operatori logici : !, &&, ||
Ca si ceilalti operatori, acesti operatori au reguli de precedenta si asociativitate care determina precis modul de evaluare a acestor expresii.

Operatori Asociativitate
() ++ (postfix) – (postfix) de la stanga la dreapta
+ (unar) – (unar) ++ (prefix) – (prefix) de la dreapta la stanga
* / % de la stanga la dreapta
+ – de la stanga la dreapta
< <= > >= de la stanga la dreapta
== != de la stanga la dreapta
&& de la stanga la dreapta
|| de la stanga la dreapta
?: de la dreapta la stanga
= += -= *= /= etc de la dreapta la stanga
, (operatorul virgula) de la stanga la dreapta

Operatorul ! este unar, spre deosebire de toti operatori (relationali, de egalitate si logici) care sunt binari. Toti operatorii vor fi prezenti in expresii ce pot lua valoarea intreaga 1 sau 0. Motivul este ca C reprezinta „false” orice expresie egala cu zero, si „true” orice expresie diferita de zero.

Exemple: In continuare, dam o lista de expresii ce se evaluaza la false

1. O expresie de tip int ce are valoarea 0;
2. O expresie de tip float ce are valoarea 0.0;
3. Caracterul null ”;
4. Pointerul NULL.

3.2 Operatori si expresii relationale

Am vazut ca operatorii <, >, <=, >= sunt toti binari. Expresiile ce contin acesti operatori pot lua valoarea 0 sau 1.

Exemple: Primele patru exemple sunt corecte, restul sunt gresite:

1. a < 3
2. a > b
3. -1.1 >= (2.2 * x + 3.3)
4. a < b < c (corecta, dar confuza)
5. a =< b
6. a < = b
7. a >> b

Fie expresia relationala „a < b”. Daca valoarea lui a este mai mica decat valoarea lui b, atunci expresia va avea valoarea 1, pe care o gandim ca fiind „true”. Daca valoarea lui a este mai mare decat valoarea lui b, atunci expresia va avea valoarea 0, pe care o gandim ca fiind „false”. Observam ca valoarea lui „a < b” este aceeasi cu valoarea lui „a – b < 0”. Folosind precedenta operatorilor aritmetici, aceasta este deci echivalenta cu „(a – b) < 0”. De altfel, pe multe masini, expresii cum sunt „a < b” sunt implementate ca fiind „a – b < 0”.

Exemple: Vom considera urmatorul tabel cu declaratii si initializari.

Presupunem ca avem declaratiile:
int i = 1, j = 2, k = 3;
double x = 5.5, y = 7.7;

Expresie Expresie echivalenta Valoare
i < j – k i < (j – k) 0
– i + 5 * j >= k + 1 ((- i) + (5 * j))) >= (k + 1) 1
x – y <= j – k -1 (x – y) <= ((j – k) – 1) 1
x + k + 7 < y / k ((x + k) + 7) < (y / k) 0

3.3 Operatori si expresii de egalitate

Expresiile pot contine si operatorii de egalitate == si !=. Expresiile ce le contin au valoarea 0 sau 1.

Exemple. Primele trei exemple sunt corecte, restul sunt gresite:

1. c == ‘A’
2. k != -2
3. x + y == 2 * x – 5
4. a = b
5. a = = b – 1
6. (x + y) =! 44

Intuitiv, o expresie de egalitate cum ar fi a == b este sau „true” sau „false”. Mai precis, daca a este egal cu b, atunci a == b intoarce valoarea 1 (true); altfel, aceasta intoarce valoarea 0 (false). O expresie echivalenta este a – b == 0 (aceasta este ceea ce se implementeaza la nivel masina).
Expresia „a != b” ilustreaza folosirea operatorului „diferit de” (sau „nu este egal cu”).

Exemple: Vom considera urmatorul tabel cu declaratii si initializari.

Presupunem ca avem declaratiile:
int i = 1, j = 2, k = 3;

Expresie Expresie echivalenta Valoare
i == j j == i 0
i != j j != i 1
i + j + k == – 2 * – k ((i + j) + k) == ((-2) * (- k)) 1

3.4 Operatori logici si expresii logice

Operatorul logic ! este unar, iar && si || sunt binari. Expresiile ce contin acesti operatori intorc valoarea 0 sau 1. Negarea logica poate fi aplicata unei expresii aritmetice sau unui tip pointer. Daca o expresie are valoarea 0, atunci expresia negata are valoarea 1. Daca expresia are o valoare diferita de 0, atunci expresia negata intoarce valoarea 1.

Exemple. Primele trei exemple sunt corecte, restul sunt gresite:

1. !a
2. !(x + 7.7)
3. !(a < b || c < d)
4. a!
5. a != b (este corecta, dar se refera la operatorul „diferit”)

Unele identitati logice (din matematica) nu se „transmit” in C. De exemplu, se stie ca „not (not s) =s”, in timp ce valoarea lui „!!5” nu este 5, ci 1. Motivul este ca operatorul „!” se asociaza de la dreapta la stanga, si deci „!!5” este echivalent cu „!(!5)”, care echivalent cu „!(0)”, ce intoarce valoarea 1.

Exemple: Vom considera urmatorul tabel cu declaratii si initializari.

Presupunem ca avem declaratiile:
int i = 7, j = 7;
double x = 0.0, y = 999.9;

Expresie
Expresie echivalenta
Valoare
! (i – j) + 1
(! (i – j)) + 1
2
! i – j + 1
((! i) – j) + 1
-6
! ! (x + 3.3)
! (! (x + 3.3))
1
! x * ! ! y
(! x) * (! (! y))
1

Operatorii logici binari && si || pot fi folositi in expresii care intorc 0 sau 1.

Exemple. Primele patru exemple sunt corecte, restul sunt gresite:

1. a && b
2. a || b
3. !(a < b) && c
4. 3 && (-2 * a + 7)
5. a &&
6. a | | b
7. a & b (corecta, dar se refera la operatii peste biti)
8. &b (corecta, dar se refera la adresa lui b)

Exemple: Vom considera urmatorul tabel cu declaratii si initializari.

Presupunem ca avem declaratiile:
int i = 3, j = 3, k = 3;
double x = 0.0, y = 2.3;

Expresie
Expresie echivalenta
Valoare
i && j && k
(i && j) && k
1
x || i && j – 3
x || (i && (j – 3))
0
i < j && x < y
(i < j) && (x < y)
0
i < j || x < y
(i < j) || (x < y)
1

3.5 Evaluare rapida (short-circuit)

Pentru expresiile ce contin && sau ||, evaluarea are loc cand s-a stabilit deja valoarea expresiei, eventual fara parcurgerea intregii expresii. Astfel, presupunem ca „expr1” se evalueaza la 0 (false). Atunci expresia expr1 && expr2 se va evalua la 0, fara a se mai face evaluarea expresiei „expr2”.
Alt exemplu, daca „expr1” se evalueaza la 1 (true), atunci expresia expr1 || expr2 se va evalua la true fara a se mai evalua expresia „expr2”.
Uneori se mai spune ca operatorii && si || sunt lazy (adica le este lene sa mai evalueze toti operanzii din expresie).

3.6 Instructiunea compusa

O instructiune compusa este un sir de declaratii si instructiuni delimitate de acolade. Ceea ce acoladele delimiteaza se numeste „bloc”. O instructiune compusa este ea insasi o instructiune.

Exemplu:

{
a = 1;
{
b = 2;
c = 3;
}
}

3.7 Instructiunea vida

Instructiunea vida se reprezinta cu semnul ; (punct si virgula). Ea se foloseste cand se doreste folosirea ei sintactica, si nu neaparat folosire semantica. Dupa cum vom vedea, aceasta se foloseste in constructii „if-else” si „for”. O expresie urmata de ; se numeste „instructiune expresie”.

Exemplu:

a = b;
a + b + c;
;
printf(„%d\n”, a);

3.8 Instructiunile „if” si „if-else”

Forma generala a instructiunii „if” este
if (expresie)
instructiune
Semantica intuitiva este simpla. Astfel, daca valoarea expresiei este true (diferita de zero), atunci se executa instructiunea, altfel nu.

Exemplu:

Instructiunea „if” de mai jos va testa daca se poate face impartirea cu y (ce trebuie sa fie diferit de 0):
if (y != 0.0)
x /= y;

Urmatoarele doua instructiuni
if (j < k)
min = j;
if (j < k)
printf(„j este mai mic decat k\n”);
se pot scrie intr-una singura
if (j < k)
{
min = j;
printf(„j este mai mic decat k\n”);
}
Instructiunea „if-else” de mai jos este foarte apropiata de instructiunea „if”. Aceasta are forma generala:
if (expresie)
instructiune1
else
instructiune2
Semantica intuitiva este de asemenea clara. Daca valoarea expresiei este diferita de zero, atunci se executa instructiune1 si „se sare” peste instructiune2. Daca valoarea expresiei este zero, atunci „se sare” instructiune1, si se executa instructiune2.

Exemplu:

Urmatorul subprogram C de mai jos calculeaza si afiseaza minimul dintre x si y.

if (x < y)
min = x;
else
min = y;
printf(„Valoarea minima = %d\n”, min);

3.9 Instructiunea „while”

„While”, „for” si „do” sunt cele trei instructiuni repetitive din limbajul C. Consideram urmatorul format general al instructiunii „while” (iteratia sau bucla „while”).

while (expresie)
instructiune
instructiune_urmatoare

Mai intai se evalueaza expresie. Daca aceasta nu este zero (deci este „true”), atunci se executa instructiunea, si control trece la inceputul buclei „while”. Astfel, corpul buclei se executa de cate ori expresie se evalueaza la „true”. Terminarea buclei are loc cand expresie ia valoarea zero (adica „false”). In acest punct, controlul se paseaza catre „instructiune_urmatoare”.

Exemplu:

while (i <= 10)
{
suma += i;
++i;
}

3.10 Instructiunea „for”

Ca si instructiunea „while”, instructiunea „for” se foloseste pentru descrierea structurilor iterative (repetitive). Astfel constructia:

for (expresie1; expresie2; expresie3)
instructiune
instructiune_urmatoare

este semantic echivalenta cu:

expresie1;
while (expresie2)
{
instructiune;
expresie3;
}
instructiune_urmatoare;

Deci, se va evalua expresie1. De obicei, aceasta se foloseste pentru initializarea buclei. Apoi, se evalueaza expresie2. Daca aceasta nu este zero („true”), atunci se executa instructiune, se evalueaza expresie3, si controlul buclei se „paseaza” la inceputul buclei (cu deosebirea ca nu se mai evalueaza expresie1). De obicei, expresie2 este o expresie logica care controleaza bucla. Acest proces continua pana cand expresie2 este 0 (false), punct in care se plaseaza controlul catre instructiune_urmatoare.

Exemplu: Exemplul de mai jos calculeaza factorialul numarului n.

factorial=1;
for (i = 1; i <= n; i++)
factorial *= i;

Orice sau toate expresiile dintr-o instructiune „for” pot lipsi, dar nu poate lipsi ;

Exemple: Exemplul de mai jos calculeaza suma numerelor intregi de la 1 la 10.

i = 1;
suma = 0;
for ( ; i <= 10; ++i)
suma += i;

Acesta se poate scrie echivalent:
i = 1;
suma = 0;
for ( ; i <= 10; )
suma += i++;

Daca, in schimb, lipseste expresie2, atunci obtinem o bucla infinita.

3.11 Operatorul „,”

Operatorul „,” are cea mai mica prioritate dintre toti operatorii din C. Este un operator binar ce are ca operanzi drept expresii si se asociaza de la stanga la dreapta. Intr-o expresie de forma:
expresie1 , expresie2
se evalueaza mai intai expresie1, apoi expresie2. Expresia „,” intoarce valoarea si tipul operandului din dreapta.

Exemplu: Presupunem ca a, b sunt de tip int. Atunci expresia „,”

a = 0, b = 1
intoarce valoarea 1 de tipul int.
Operatorul „,” este deseori folosit in instructiunea „for”.

Exemplu: Exemplul de mai jos calculeaza factorialul numarului n (reluare).

for (factorial = 1, i = 1; i <= n; i++)
factorial *= i;

Exemplu: Revenim asupra unui exemplu precedent (suma primelor N numere naturale)

for (suma = 0, i = 1; i <= n; ++i)
suma += i;
se poate scrie, echivalent, in
for (suma = 0, i = 1; i <= n; suma += i, ++i);

Intrebare: Ce se intampla cu valoarea lui suma daca intervertim instructiunile

suma += i cu ++i

Exemplu:

for (i=0, p = head; p != NULL; p=p -> next )
…..

3.12 Instructiunea „do”

Instructiunea „do” poate fi considerata o varianta a instructiunii „while”. Deosebirea consta in faptul ca pentru instructiunea „while” testul se face la inceputul ciclului, iar pentru „do” la sfarsit. Consideram constructia de forma:
do
instructiune
while (expresie);
instructiune_urmatoare

La inceput se executa instructiune, apoi se evalueaza expresie. Daca valoarea lui expresie este diferita de 0 („true”), atunci controlul se paseaza la inceputul instructiunii „do”, si procesul se repeta. Daca expresie se evalueaza la 0 (false), atunci controlul se paseaza la instructiune_urmatoare.

Exemplu: Suma unor numere intregi diferite de 0

suma = i = 0;
do
{
suma += i;
scanf(„%d”, &i);
}
while (i > 0);

3.13 Instructiunea „goto”

Instructiunea „goto” (salt neconditionat) este considerata opusa programarii structurate. Sfatul general valabil este evitarea acestei instructiuni. Totusi, in unele cazuri se poate folosi (cand simplifica controlul, cand face codul mai eficient). O instructiune de etichetare are forma: eticheta : instructiune unde eticheta este un identificator.

Exemple:

bye: exit(1);
eticheta1: a = b + c;

333: a = b + c; (exemplu gresit, de ce ?)
Controlul programului poate fi transferat neconditionat catre o instructiune de etichetare astfel goto eticheta;

3.14 Instructiunile „break” si „continue”

Cele doua instructiuni break; si continue; intrerup controlul normal al programelor. Instructiunea „break” va cauza iesirea din bucla in care se afla sau din instructiunea „switch”. Instructiunea „continue” se poate afla numai in instructiuni „for”, „while” si „do”. Ea are rolul de a trasmite controlul catre sfarsitul buclei respective.

Exemple:

while (1)
{
scanf(„%lf”, &x);
if (x < 0.0)
break; /* iesim cand x este negativ */
printf(„%lf\n”, sqrt(x));
}
while (contor < n)
{
scanf(„%lf”, &x);
if (x > -0.01 && x < =0.01)
continue; /* valorile mici nu se iau in considerare */
++contor;
suma += x;
}

3.15 Instructiunea „switch”

„Switch” este o instructiune conditionala ce generalizeaza o instructiune „if-else”.

Exemplu:

switch (val)
{
case 1:
++contor_a;
break;
case 2:
case 3:
++contor_b;
break;
default:
++contor_c;
}

Corpul unei instructiuni „switch” este un exemplu de instructiune compusa. Expresia de control dintre paranteze (ce urmeaza cuvantului switch) trebuie sa fie de tip integral (vom reveni intr-un alt capitol). Dupa evaluarea lui val, controlul sare la eticheta corespunzatoare valorii lui val. De obicei, ultima instructiune dintr-un „case” este de obicei „break”. Daca nu exista „break”, atunci se vor executa si instructiunile din urmatoarele „case”-uri.
Atentie ! Omiterea scrierii lui „break” este foarte frecventa !! Poate apare cel mult un „default” (in general pe ultima pozitie). Cuvintele rezervate „case” si „default” pot apare numai in interiorul unui „switch”.

3.16 Operatorul conditional

Operatorul „?:” este mai putin obisnuit deoarece este ternar (cu trei argumente). Forma generala este: expresie1 ? expresie2 : expresie3

Mai intai, se evalueaza expresie1. Daca aceasta este diferita de 0 (true), atunci se evalueaza expresie2, si aceasta va fi valoarea returnata de intreaga expresie conditionala. Daca expresie1 este 0 (false), atunci se evalueaza expresie3, si aceasta va fi valoarea intregii expresii conditionale.

Exemplu: Instructiunea

if (y < z)
x = y;
else
x = z;

este echivalenta cu
x = (y < z) ? y : z;

Operatorul ?: are aceeasi prioritate cu operatorul de asignare si se asociaza de la dreapta la stanga.

Categorii:Tutoriale C++
  1. Niciun comentariu până acum.
  1. No trackbacks yet.

Lasă un răspuns

Completează mai jos detaliile despre tine sau dă clic pe un icon pentru autentificare:

Logo WordPress.com

Comentezi folosind contul tău WordPress.com. Dezautentificare / Schimbă )

Poză Twitter

Comentezi folosind contul tău Twitter. Dezautentificare / Schimbă )

Fotografie Facebook

Comentezi folosind contul tău Facebook. Dezautentificare / Schimbă )

Fotografie Google+

Comentezi folosind contul tău Google+. Dezautentificare / Schimbă )

Conectare la %s

%d blogeri au apreciat asta: