Sunteți pe pagina 1din 9

Cursul 9.

Instruciuni C\C++
(partea a II-a)

III. Instruciuni de ciclare


Instruciunile de ciclare (repetitive, iterative, etc) sunt utilizate n situaia n care o anumit
secven de cod trebuie executat de mai multe ori n mod consecutiv, numrul de repetiii fiind fix,
stabilit iniial, sau variabil, depinznd de rezultatul aciunii repetate.
Limbajul C pune la dispoziia programatorilor trei instruciuni de ciclare: while, do-while i
for, toate trei utiliznd pentru continuarea ciclrii o condiie de tip ct timp este adevrat c ,
diferena dintre ele fiind dat, n principal, de momentul testrii condiiei de ciclare: n cazul
instruciunii while testarea are loc naintea fiecrei execuii a aciunii repetate (testare anterioar),
n cazul do-while testarea se face la reluare, dup fiecare execuie (testare posterioar), iar n cazul
instruciunii for testarea se face analog cazului while, instruciunea for avnd ns prevzut i
evaluarea unei anumite expresii nainte de fiecare reluare, precum i o secven iniial, executat
naintea intrrii n ciclare.
Instruciunile repetitive pstreaz controlul fluxului de execuie al programului pn cnd
are loc ieirea din ciclare. O ieire din ciclare poate fi normal, atunci cnd controlul este preluat de
urmtoarea instruciune din textul surs n urma evalurii condiiei de repetare a ciclrii, sau poate fi
forat, prin executarea unei instruciuni de salt aflate n corpul instruciunii repetitive.
In continuare vom descrie cele trei instruciuni iterative ale limbajului C n situaia n care
ieirile sunt normale, urmnd ca ieirile forate din ciclare s fie tratate o dat cu instruciunile de
salt.

7. Instruciunea while
Sintaxa: while (expresie-test) instruciune-corp
Instruciunea while i insereaz n mod repetat n fluxul de execuie instruciunea sa corp,
att timp ct expresia-test este adevarat (are o valoare nenul). Este asemntoare cu instruciunea
if, cu diferena esenial c instruciunea while pstreaz controlul dup executarea instruciunii
corp, relund evaluarea expresiei-test. Controlul execuiei trece la urmtoarea instruciune din textul
surs al programului (dac n corp nu sunt prevzute salturi) numai atunci cnd expresia test devine
fals (egal cu zero). Dac expresia test este fals de la bun nceput, instruciunea corp nu este
executat niciodat.
Tipul expresiei-test trebuie sa fie scalar (numeric sau pointer) i la evaluare sunt completate
toate efectele ei secundare naintea lurii deciziei de contiunare sau de terminare a ciclrii.
Instruciunea-corp poate fi de orice tip (inclusiv o instruciune while), dar ca s aibe sens utilizarea
ei trebuie sa fie o instruciune efectiv i nu o declaraie, de exemplu. De regul, instruciunea corp
este o instruciune compus, coninnd o secven de cod care descrie aciunea care trebuie repetat.
De exemplu, pentru a tipri codurile ASCII ale caracterelor stringului text, se poate utiliza
1

urmtorul ir de instruciuni:

int i=0;
while(text[i]!='\0'){
cout<<(int)text[i]<<" ";
i++;
}

Dac irul de caractere este vid (adic text[0]== '\0'), nu este tiparit nici un cod ASCII.
Secventa de mai sus poate fi compactat astfel:

int i=0;
while(text[i]!='\0')
cout<<(int)text[i++]<<" ";
cout<<endl;

sau

int ch,i=0;
while((ch=text[i++])!='\0')
cout<<ch<<" ";
cout<<endl;

Primele dou variante sunt complet echivalente, a treia, dei execut acelai lucru, difer de primele
prin valoarea indexului i la ieirea din ciclare: deoarece n ultima variant incrementarea indexului
are loc la evaluarea condiiei de continuare, i este incrementat i n cazul n care se decide ieirea
din ciclare, astfel c n final valoarea indexului depete cu o unitate locul terminatorului de string
(caracterul nul).

8. Instruciunea do-while
Sintaxa: do instruciune-corp while (expresie-test);
Instruciunile while i do-while sunt foarte asemntoare, singura diferen aprnd doar la
iniierea ciclrii: la start, do-while execut o dat, n mod necondiionat, instruciunea sa corp i
numai dup aceasta intr n ciclul testare repetare, spre deosebire de while care ncepe direct cu
evaluarea expresiei test. In concluzie, instruciunea do-while este echivalent cu urmtoarea secven de instruciuni:
instruciune-corp
while (expresie-test) instruciune-corp
De remarcat c sintaxa instruciunii do-while prevede existena terminatorului ;care nu
poate fi nlocuit cu nimic altceva (aici nu are sensul de instruciune nul).
Instruciunea do-while este de preferat n locul instruciunii while n situaia n care aciunea
iterat trebuie executat cel puin o dat. De exemplu, n programul urmtor utilizatorul trebuie s
introduc mai nti un numr pentru ca acesta s poat fi testat dac este sau nu strict pozitiv:
2

#include<iostream>
using namespace std;
int main(){
int a;
do{
cout<<"Dati un numar strict pozitiv, a=";
cin>>a;
}while(a<=0);
cout<<"Avem a="<<a<<endl;
return 0;
}
/* EXEMPLU:
Dati un numar
Dati un numar
Dati un numar
Avem a=12
Press any key

pozitiv, a=-2
pozitiv, a=-10
pozitiv, a=12
to continue . . .*/

Un alt exemplu: pentru a copia tot stringul mesaj, inclusiv terminatorul de string, este de
preferat utilizarea instruciunii do-while:
#include<iostream>
using namespace std;
const int dimMax=100;
int main(){
char ch,text[dimMax],mesaj[dimMax]="Un exemplu banal!";
int i=0;
do {
ch=text[i]=mesaj[i];
i++;
} while (ch!='\0');
cout<<text<<endl;
return 0;
}

Dac irul de caractere text este vid, este copiat numai codul caracterului nul (zero).
Atenie; urmtoarea compactificare duce la o expresie ambigu:

do
ch=text[i]=mesaj[i++];
while (ch!='\0');
cout<<text<<endl;

deoarece nu se poate preciza momentul exact al incrementrii indexului i.


Instruciunile while i do-while sunt preferate n locul instruciunii for atunci cnd expresiatest nu depinde direct de numrul de ordine al iteraiei curente, aa cum a fost cazul n exemplele
date.

9. Instruciunea for
Sintaxa: for ( expresie-inial; expresie-test; expresie-reluare) instruciune-corp
Instruciunea for, cu o sintax mult mai complex dect celelalte instruciuni de ciclare,
furnizeaz o scriere compactat a etapelor standard de execuie a unui proces iterativ: iniializarea
variabilelor naintea startului, evaluarea testului de ciclare, execuia aciunilor din corpul ciclului,
3

actualizarea variabilelor implicate n expresia-test, reluarea testrii. In general (cu cteva excepii
care vor fi precizate ulterior) instruciunea for este echivalent cu urmatoarea secven de
instruciuni:
expresie-inial;
while ( expresie-test) {
instruciune-corp
expresie-reluare;
}
De exemplu, iniializarea cu zero a componentelor tabloului tab executat de secvena de
instruciuni:

i=0;
while (i<100){
tab[i]=0;
i++;
}

poate fi efectuat de o singur instruciune for:

for ( i=0; i<100; i++) tab[i]=0;

Execuia instruciunii for ncepe cu evaluarea expresie-iniiale i completarea tuturor


efectelor sale secundare. Expresia iniial poate fi de orice tip, scopul ei este de iniializare a
valorilor variabilelor implicate n ciclare (dac trebuie facute mai multe atribuiri se poate folosi
operatorul virgul, desigur). Ea este evaluat o singur dat, imediat nainte de intrarea n ciclarea
propriu-zis. Dup evaluarea expresiei de iniializare se trece la evaluarea expresiei-test (i
completarea efectelor ei secundare). Expresia test trebuie s fie de tip scalar. Dac rezultatul
evaluarii e fals execuia instruciunii for se ncheie aici, iar controlul este preluat de urmatoarea
instruciune din textul surs. Dac expresia-test este adevarat se continu cu execuia instruciuniicorp. Dup finalizarea aciunilor descrise de corpul ciclui for (instruciunea-corp) i imediat nainte
de reluarea testrii este evaluat expresia-reluare. Expresia-reluare poate avea orice tip, ea este
utilizat mai ales pentru actualizarea valorii variabilei index. Dup completarea efectelor
secundare a expresiei-reluare se reia procesul iterativ prin re-evaluarea expresiei test.
Oricare dintre cele trei expresii din antetul instruciunii for poate lipsi, doar prezena celor
dou simboluri punct i virgul este obligatorie. In cazul n care lipsete expresia-test (fapt interzis
pentru if sau pentru while) se consider ca testul de reluare a iteraiei este n mod implicit satisfcut. In acest caz, dac nu este prevzut ieirea forat (prin salt) din ciclare, execuia
instruciunii for continu la nesfrit i, n consecin, blocheaza execuia programului.
De reinut: urmtoarea form a instruciunei for:
for ( ; expresie-test; ) instruciune-corp
este echivalent cu
while ( expresie-test ) instruciune-corp
n timp ce forma:
for ( ; ; ) instruciune-corp
este echivalent cu
while ( 1 ) instruciune-corp.
4

Urmtoarele exemple ilustreaz modul uzual de utilizare al instruciunii for.


Exemplul 1. Sumarea din trei n trei a elementelor unui tablou uni-dimensional, tab, ncepand cu
tab[2]:

for( suma=0,i=2; i<n; i+=3) suma+=tab[i];

Exemplul 2. Inversarea ordinei elementelor tabloului tab:

for( i=0,j=n-1; i<j; i++,j--){


aux=tab[i];
tab[i]=tab[j];
tab[j]=aux;
}

Exemplul 3. Determinarea valorii maxime a elementelor matricei mat:

for(valMax=mat[0][0],i=0; i<n; i++)


for (j=0; j<m; j++)
if (valMax < mat[i][j]) valMax=mat[i][j];
cout<<"valoarea maxima="<<valMax<<endl;

In final menionm c n C++ sintaxa instruciunii for permite ca n locul expresiei iniiale s apar
o instruciune declaraie, n acest caz domeniul de vizibilitate al variabilelor declarate aici este
restrns la blocul format de instruciunea for respectiv. Mai precis, urmtoarea secven de cod
int n=10;
for(int i=1,s=0;i<=n; i++){
s+=i;
cout<<"i="<<i<<" s="<<s<<endl;
}

este echivalent cu
int n=10;
{
int i=1,s=0;
while(i<=n){
s+=i;
cout<<"i="<<i<<" s="<<s<<endl;
i++;
}
}

Exerciiu: ce eroare de compilare produce secvena urmtoare?


int suma(int n)
{
for(int i=0,s=0; i<n; i++)
s+=i;
return s;
}

IV. Instruciuni de salt


10. Instruciunea break
Instruciunea break are sintaxa
break;
i este este folosit pentru a iei imediat dintr-o instruciune de ciclare sau dintr-un switch. Ea
transfer controlul instruciunii imediat urmtoare celei prsite. Instruciunea break poate fi
folosit numai n aceste dou situaii, dac ea apare fr s fie n corpul unei ciclri sau al unui
switch avem o eroare la compilare. In cazul instruciunilor imbricate (for n for, etc) break ncheie
numai execuia instruciunii n care este direct inclus.
Exemplu:
#include<iostream>
using namespace std;
int main(void){
int i, j;
for (i = 0; i<5; i++){
cout << "i=" << i;
for (j = 0; j<5; j++){
if (i == j) {
cout << " break ";
break;
}
cout << " j=" << j;
}
cout << endl;
}
return 0;
}

/* REZULTAT
i=0 break
i=1 j=0 break
i=2 j=0 j=1 break
i=3 j=0 j=1 j=2 break
i=4 j=0 j=1 j=2 j=3 break
Press any key to continue . . .*/

11. Instruciunea continue


Instruciunea continue are sintaxa
continue;
i este este folosit n instruciuni de ciclare (i numai acolo) pentru a ncheia n mod forat execuia
iteraiei curente i a trece la urmtoarea iteraie. In interiorul unei bucle while sau do-while, la
ntlnirea instruciunii continue are loc un salt direct la re-evaluarea expresiei test, iar n cazul
instruciunii for se trece mai nti la evaluarea expresiei de reluare i apoi la evaluarea expresiei
test.
6

Exemplu:
#include<iostream>
using namespace std;
int main(void){
int i, j;
for (i = 0; i<5; i++){
cout << "i=" << i;
for (j = 0; j<5; j++){
if (i == j) {
cout << " continue ";
continue;
}
cout << " j=" << j;
}
cout << endl;
}
return 0;
}

/* REZULTAT
i=0 continue j=1 j=2 j=3 j=4
i=1 j=0 continue j=2 j=3 j=4
i=2 j=0 j=1 continue j=3 j=4
i=3 j=0 j=1 j=2 continue j=4
i=4 j=0 j=1 j=2 j=3 continue
Press any key to continue . . .*/

Iat o ilustrare a utilizrii instruciunilor break i continue n rezolvarea urmtoarei probleme: s se scrie o funcie care afieaz numai valorile comune a doi vectori, fiecare valoare fiind
afiat o singur dat.
#include<iostream>
using namespace std;
//afiseaza valorile comune o singura data
void afisare(int a[], int b[], int dim){
for (int i = 0; i<dim; i++){
double val = a[i];
//aflam daca val este valoare comuna
int eValoareComuna = 0;
for (int j = 0; j < dim; j++){
if (b[j] != val) continue; //->j++
eValoareComuna = 1;
break; //oprim for-ul dupa j
}
if (!eValoareComuna) continue;
//->i++
//val este valoare comuna
//aflam daca a mai fost afisata
int aFostAfisata = 0;
for (int k = 0; k<i; k++){
if (a[k] != val) continue; //->k++
aFostAfisata = 1;
break; //oprim for-ul dupa k
}
if (aFostAfisata) continue;
//->i++
//val este valoare comuna
//nu a mai fost afisata
//o afisam
cout << val << ' ';
}
cout << endl;
}

int main(){
const int dim = 10;
int a[dim] = { 1, 7, 3, 4, 4, 3, 7, 3, 9, 0 };
int b[dim] = { 0, 9, 3, 5, 1, 3, 7, 3, 0, 1 };
afisare(a, b, dim);
return 0;
}

/*REZULTAT:
1 7 3 9 0
Press any key to continue . . .*/

12. Instruciunea return


Instruciunea return permite unei funcii s transfere controlul napoi funciei apelante, (sau, n
cazul funciei main, returnarea controlului ctre sistemul de operare).
Execuia unei funcii care trebuie s returneze o valoare se ncheie atunci cnd controlul
ntlnete o instruciune return cu sintaxa:
return expresie-rezultat;
caz n care se evalueaz expresia-rezultat iar rezultatul obinut este transferat funciei apelante.
Funciile care nu trebuie s returneze nimic (cele a cror declaraie ncepe cu void) i
ncheie execuia atunci cnd controlul ntlnete o instruciune return fr expresie rezultat, sau la
ntlnirea acoladei care nchide corpul funciei.
Exemplu:
#include<iostream>
using namespace std;
int dist(int a, int b){
if(a>b) return a-b;
return b-a;
}
void panaLaPrimulZero( int tab[], int dim){
int i=0;
for(i=0;i<dim;i++){
cout<<tab[i]<<" ";
if(tab[i]==0) return;
}
}
int main(void){
const int dim=6;
int v[]={1,2,3,0,4,5};
int i;
for(i=0;i<dim;i++){
v[i]=dist(i,v[i]);
}
panaLaPrimulZero(v,6);
cout<<endl;
return 0;
}
/* REZULTAT
1 1 1 3 0
Press any key to continue
*/

13. Instruciunea goto


Instruciunea goto transfer controlul execuiei dintr-un anumit punct al corpului unei funcii
la o instruciune etichetat aflat n interiorul aceleiai funcii. Exemplu:
#include<iostream>
using namespace std;
int main(){
int a;
cout<<"a="; cin>>a;
if(a>0) goto pozitiv;
if(a<0) goto negativ;
cout<<"a==0"<<endl;
GATA:
cout<<"Gata, am terminat."<<endl;
return 0;
pozitiv:
cout<<"a>0"<<endl;
goto GATA;
negativ:
cout<<"a<0"<<endl;
goto GATA;
cout<<"Eu cand apar pe monitor?"<<endl;
}

Sintaxa instruciunii goto este urmtoarea:


goto etichet;
O etichet este format dintr-un identificator urmat de simbolul dou puncte. O instruciune
este etichetat dac exact n faa sa se afl una sau mai multe etichete. O etichet nu poate s apar
de mai multe ori n corpul aceleiai funcii, domeniul de vizibilitate al unei etichete fiind restrns la
corpul funciei n care apare. Aceste etichete sunt utilizate numai de instruciunea goto, n orice alt
context o instruciune etichetat este executat fr s se in seama de prezena etichetei.
Deoarece urmrirea salturilor ctre etichete reduce mult claritatea programului, este recomandat utilizarea salturilor date de break, continue sau return n locul instruciunii goto.
Un exemplu de utilizare justificat: ieirea forat din bucle imbricate:
int main(void){
const int dim=10;
int mat[dim][dim];
int i,j;
citeste(mat,dim);
for(i=0;i<dim;i++){
for(j=0;j<dim;j++){
if(mat[i][j]==0) goto stop;
cout<<1.0/mat[i][j]<<endl;
}
}
stop: cout<<"GATA"<<endl;
return 0;
}

Dac n matricea mat nu exist elemente nule sunt afiate toate inversele elementelor i apoi apare
textul "GATA", altfel afiarea se ncheie la prima apariie a lui zero. Se poate nlocui goto cu
return dac afiarea se efectueaz ntr-o funcie adecvat.
9

S-ar putea să vă placă și