Sunteți pe pagina 1din 7

6.

Bucle
n capitolul trecut am vzut cum putem selecta diferite instruciuni pentru execuie folosind instruciunea if. O bucl este o structur de control care provoac executarea unei instruciuni sau a unei secvene de instruciuni n mod repetat. Instruciunile se execut atta timp ct sunt ndeplinite una sau mai multe condiii. Vom descrie diferite tipuri de bucle i vom vedea cum se pot implementa acestea folosind instruciunea while. Vom prezenta, de asemenea, buclele imbricate.

6.1

Instruciunea while

Aceast instruciune, ca i if, testeaz o condiie. Sintaxa ei este urmtoarea: while(expresie) Instruciune Exemplu while(valIn != 25) cin >> valIn; Instruciunea care se execut n mod repetat se numete corpul buclei. Condiia din instruciunea while poate fi o expresie de orice tip de dat. Aproape ntotdeauna ea este o expresie logic. Instruciunea while din exemplul de mai sus spune urmtorul lucru: Dac valoarea expresiei este true (nenul), execut corpul buclei iar apoi revino i testeaz din nou expresia. Dac expresia este false (zero), treci de corpul buclei. Dac expresia este fals de la nceput, corpul nu se execut niciodat. n figura de mai jos artm n mod schematic modul de execuie a instruciunii while.

while (expresie)
false true

Instruciune

Instruciunea 2 Corpul buclei poate fi i un bloc, fapt care ne permite s executm mai multe instruciuni n mod repetat. Exemplu while(expresie) { ... } Blocul se execut pn cnd expresia devine fals.

Programarea calculatoarelor i limbaje de programare I

6.2

Fazele de execuie a unei bucle

1. Intrarea n bucl. Este punctul n care programul ajunge la prima instruciune din interiorul buclei. 2. Iterarea. De fiecare dat cnd se execut corpul buclei, spunem c facem cte o trecere prin bucl. Aceast trecere se numete iteraie. 3. Testul buclei. Reprezint punctul n care se evalueaz expresia din instruciunea while. n urma acestei evaluri se poate lua decizia de a se ncepe o nou iteraie sau de a trece la instruciunea imediat urmtoare buclei. 4. Condiia de terminare. Este condiia care provoac ieirea din bucl, trecndu-se la prima instruciune de dup bucl. Aceast condiie apare n instruciunea while. 5. Ieirea din bucl. ntr-o bucl while, ieirea din bucl apare cnd expresia din instruciunea while este false sau 0. n acest moment, se ntrerupe repetarea corpului buclei. Dei condiia de terminare poate deveni valid n mijlocul corpului buclei, iteraia curent este executat pn la capt i numai dup aceea calculatorul verific din nou expresia din instruciunea while.

6.3

Implementarea buclelor folosind instruciunea while

n rezolvarea problemelor se pot ntlni dou tipuri majore de bucle: - bucla controlat de un contor; - bucla controlat de un eveniment. Dac n timpul unui antrenament sportiv vi se cere s alergai de 3 ori n jurul stadionului, este vorba de o bucl controlat de contor. Dac, n schimb, vi se cere s alergai pn cnd vei auzi sunetul fluierului, avem de a face cu o bucl controlat de un eveniment.

Bucla controlat de un contor


O astfel de bucl folosete o variabil numit variabil de control al buclei. naintea buclei ea este iniializat, adic i se atribuie o valoare iniial. Apoi, n fiecare iteraie a buclei ea trebuie incrementat. Exemplu int contorBucla = 1; //initializare while(contorBucla <= 10) //test { ... //actiune care se repeta contorBucl++; //incrementare } n acest exemplu, contorBucla este variabila de control al buclei. Ea este iniializat cu valoarea 1 nainte de intrarea n bucl. Instruciunea while testeaz expresia contorBucla <= 10 i execut bucla atta timp ct expresia este adevrat. Ultima instruciune a buclei incrementeaz variabila contorBucla. Variabilele folosite n acest fel se numesc contoare. La folosirea acestor bucle, programatorul trebuie s urmreasc iniializarea contorului naintea instruciunii while. Trebuie, de asemenea, s urmareasc dac

Programarea calculatoarelor i limbaje de programare I

n interiorul buclei valoarea lui se modific n aa fel nct la un moment dat condiia s devin fals. O bucl din care programul nu poate iei deloc se numete bucl infinit. Aceast situaie apare atunci cnd n program se omite incrementarea contorului.

Bucla controlat de un eveniment


Pentru aceast categorie de bucle condiia de terminare depinde de un eveniment care poate aprea n timpul execuiei corpului buclei. Vom studia dou tipuri de bucle controlate de evenimente: - bucla controlat de o valoare de semnalizare (valoare santinel); - bucla controlat de sfritul unui fiier (EOF). Bucla controlat de o valoare de semnalizare (valoare santinel) Aceste bucle se folosesc n special atunci cnd se prelucreaz volume mari de date. La fiecare iteraie se citete i se prelucreaz cte un set de date. Anumite valori dintre cele citite vor semnaliza ncheierea buclei while. Bucla while i continu execuia atta timp ct valorile citite nu sunt cele de semnalizare (santinel). Exemplu int luna, ziua; cin >> luna >> ziua; //citeste primul set de date while(!(luna == 2 && ziua == 31)) { ... //procesare cin >> luna >> ziua; //urmatorul set de date } Este bine ca valorile santinel s fie dintre cele care nu apar n mod obinuit ntre datele valide de intrare. nainte de intrarea n bucl este citit primul set de date. Dac nu este vorba despre valorile santinel, ele sunt procesate. La sfritul buclei se citete urmtorul set de date, revenindu-se apoi la nceputul buclei. Bucla se execut pn la citirea valorilor santinel. Acestea nu sunt prelucrate i conduc la ieirea din bucl. Exemplu Atunci cnd prelucrm date de tip char putem folosi caracterul newline ca valoare santinel: char inChar; cin.get(inChar); while(inChar != \n) { cout << inChar; cin.get(inChar); } Ce se ntmpl dac nu introducem valoare santinel? Un program interactiv ne va cere n continuu noi valori. Dac intrrile n program se fac dintr-un fiier i datele se epuizeaz naintea apariiei valorii santinel, stream-ul intr in fail state. O greeal frecvent n urma creia programul poate avea o evoluie nedorit este folosirea neintenionat a operatorului = n locul lui ==. Exemplu char inChar, valSemnal; cin >> inChar >> valSemnal; while(valSemnal = 1) 3

Programarea calculatoarelor i limbaje de programare I

//din greseala am folosit = in loc de == ... cin >> inChar >> valSemnal;

} Aceast eroare creeaz o bucl infinit. Expresia din instruciunea while este o asignare i nu o expresie logic. Calculatorul evalueaz valoarea variabilei valSemnal dup asignare. Aceasta va fi 1 i va fi interpretat ca fiind true. Astfel, expresia testat n exemplul de mai sus stocheaz valoarea 1 n valSemnal nlocuind valoarea care tocmai a fost citit. Pentru c expresia este tot timpul true, bucla nu se ntrerupe niciodat. Bucla controlat de sfritul unui fiier (EOF) Dup ce programul citete i ultimele date din fiierul de intrare, calculatorul ajunge la sfritul fiierului (EOF, end of file). n acest moment starea stream-ului este normal. Dar dac ncercm s citim o nou dat, stream-ul intr n fail state. Putem folosi acest comportament n avantajul nostru n buclele while n care se citete un numr necunoscut de valori. Starea de eroare a stream-ului poate fi interpretat ca valoare santinel pentru c numele stream-ului poate aprea ntr-o expresie logic la fel ca o variabil booleean. ntr-un astfel de test, rezultatul este true dac ultima operaie de intrare/ieire a avut succes, sau este false dac aceasta a euat. S presupunem c avem un fiier de date care conine valori ntregi. Putem scrie: int inVal; inData >> inVal; while(inVal) { cout << inVal << endl; inData >> inVal; } Dac fiierul de date conine numerele 10, 20 i 30, primele 3 citiri se vor realiza corect. Chiar i dup citirea lui 30 starea stream-ului este normal. Dac dorim s citim dup sfritul fiierului, ns, stream-ul va intra n stare de eroare. Aceasta nseamn c valoarea expresiei logice din while va fi false provocnd ieirea din bucl. Trebuie spus c orice eroare de citire conduce la intrarea stream-ului n fail state. Similar, se poate folosi i stream-ul de intrare cin. n sistemele UNIX, combinaia de taste CTRL-D, iar n sistemele DOS combinaia de taste CTRL-Z au semnificaia EOF pentru intrri interactive.

6.4
Pentru despre -

Operaii n bucl
a avea sens, o bucl trebuie s realizeze o operaie. Vom discuta contorizare; nsumare; pstrarea unei valori anterioare.

Programarea calculatoarelor i limbaje de programare I

Contorizarea
O operaie comun este memorarea numrului de iteraii executate. Programul care urmeaz citete i numr caracterele dintr-o propoziie, pn la apariia punctului. Exemplu #include <iostream> using namespace std; int main() { char inChar; int count = 0; //initializarea contorului cin.get(inChar); //citirea primului caracter while(inChar != '.') { count++; //incrementarea contorului cin.get(inChar); //citirea urmatorului caracter } cout << "Propozitia are " << count << " caractere" << endl; return 0; } Dup terminarea buclei, count va conine cu 1 mai puin dect numrul de caractere citite, adic nu numr i valoarea santinel (.). Facem o prim citire naintea buclei pentru c aceasta este controlat de un caracter de semnalizare. O variabil care numr cte iteraii se execut se numete contor de iteraii . n exemplul nostru, variabila count este un contor de iteraii.

nsumarea
O alt operaie care se poate implementa cu ajutorul buclelor este nsumarea unui set de valori. Exemplu #include <iostream> using namespace std; int main() { int numar; int suma = 0; int contor = 1; while(contor <= 5) { cin >> numar; suma = suma + numar; contor++; } cout << "Suma este " << suma << endl; return 0; }

Programarea calculatoarelor i limbaje de programare I

Iniializm suma cu 0 nainte de nceputul buclei. Atunci cnd se execut prima dat instruciunea suma = suma + numar; se adaug valoarea curent a variabilei suma la valoarea variabilei numar pentru a forma noua valoare a variabilei suma. Dup executarea buclei, variabila suma va conine suma celor 5 valori citite, contor va conine valoarea 6 i numar ultima valoare citit.

Pstrarea unei valori anterioare


Avem uneori nevoie n program de o valoare anterioar a unei variabile. S presupunem c dorim s scriem un program care contorizeaz numrul de operatori != dintr-un fiier surs C++. Va trebui s numrm de cte ori apare semnul ! urmat de =. De fiecare dat vom citi din fiierul de intrare un caracter pstrnd ultimele dou valori n dou variabile diferite. La fiecare iteraie valoarea curent devine valoare anterioar i apoi se citete o nou valoare. Bucla se termin cnd se ajunge la EOF. Exemplu #include <iostream> #include <fstream> using namespace std; int main() { int contor = 0; char carAnterior; char carCurent; ifstream inFisier; inFisier.open("main.cpp"); inFisier.get(carAnterior); inFisier.get(carCurent); while(inFisier) { if(carCurent == '=' && carAnterior == '!') contor++; carAnterior = carCurent; inFisier.get(carCurent); } cout << contor << " operator(i) != au fost gasiti in fisier" << endl; return 0;

} Contorul din acest exemplu este un contor de evenimente. El este o variabil care se incrementeaz atunci cnd apare un anumit eveniment. Este iniializat cu valoarea 0 spre deosebire de contorul de iteraii din exemplul precedent care este iniializat cu 1.

Programarea calculatoarelor i limbaje de programare I

6.5

Instruciuni while imbricate

Am studiat n capitolul anterior modul n care se pot scrie instruciunile if imbricate. Este posibil s folosim i instruciuni while imbricate. Exemplu Ne propunem s numrm cte caractere ; sunt pe fiecare linie dintr-un fiier. #include <iostream> #include <fstream> using namespace std; int main() { ifstream inFisier; inFisier.open("main.cpp"); char inChar; inFisier.get(inChar); while(inFisier) { int contorPunctVirgula = 0; while(inChar != '\n') { if(inChar == ';') contorPunctVirgula++; inFisier.get(inChar); } cout << contorPunctVirgula << endl; inFisier.get(inChar); } return 0; } S notm c am omis prima citire pentru bucla interioar. Aceasta a fost deja fcut naintea buclei exterioare. Dac o fceam, primul caracter citit s-ar fi pierdut nainte de a-l testa. ablonul sintactic al buclelor imbricate este: Iniializarea_buclei_exterioare while(condiia_buclei_exterioare) { ... Iniializarea_buclei_interioare while(condiia_buclei_interioare) { Procesarea_i_actualizarea_buclei_interioare } ... Actualizarea_buclei_exterioare } Fiecare bucl are propria iniializare, testare i actualizare. Se poate ca bucla extern s nu fac nicio procesare. Pe de alt parte, bucla interioar poate fi o mic parte a procesrii realizate de bucla exterioar. 7

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