curs_4_lp

Download curs_4_LP

If you can't read please download the document

Upload: icarockett

Post on 17-Sep-2015

214 views

Category:

Documents


0 download

DESCRIPTION

Curs limbaje de programare

TRANSCRIPT

Programare C / cap 1-6

5

4.5. Instruciuni de ciclare Pentru obinerea repetat (ciclic) sau iterativ a unor prelucrri, care apar frecvent n algoritmi, se utilizeaz instruciunile ciclice. Prelucrrile ciclice ce trebuie efectuate constituie corpul ciclului. Un ciclu se termin dup un numr finit de repetri ca urmare a nendeplinirii unei condiii (test). Dup momentul n care are loc testarea acestei condiii, fa de corpul ciclului, instruciunile de ciclare se mpart n dou clase :- cicluri cu test la nceput (test iniial);- cicluri cu test la sfrit (test final).ncheierea execuiei unui ciclu, denumit i ieirea din ciclu, deci a prelucrrilor descrise n corpul acestora, se poate face n dou moduri:- ieire normal, care se datoreaz modificrii condiiei testate de ciclu n corpul acestuia n sensul nendeplinirii ei;- ieire forat prin utilizarea n corpul ciclului a unei instruciuni speciale, care ntrerupe execuia ciclului.Iniializrile datelor din corpul ciclului sunt realizate nainte de a ncepe instruciunea de ciclare. Exist trei instruciuni de ciclare dintre care dou cu test la nceput (while i for) i una cu test la sfrit (do-while). Condiia de testare, pentru oricare dintre cicluri, este reprezentat de o expresie cu valoare de tip ntreg interpretat ca valoare logic astfel :- adevrat, adic condiie ndeplinit, dac valoarea expresiei este diferit de zero; n acest caz se execut instruciunile din corpul ciclului, dup care se evalueaz din nou expresia de testat;- fals, adic condiie nendeplinit, dac valoarea expresiei este zero, i care are ca efect ncetarea (normal) a execuiei instruciunii de ciclare.O diferen major intre cele dou tipuri de cicluri este aceea c ciclurile cu test iniial pot s nu se execute nici o dat, dac condiia de testat nu este ndeplinit nc de la nceput, n timp ce ciclul cu test la sfrit se execut cel puin o dat, ntruct se execut corpul ciclului i apoi se testeaz condiia de sfrit de ciclu.

4.5.1. Instruciunea whileSintaxa acestei instruciuni este: while (expresie) instruciune;Efectul acestei instruciuni const n evaluarea repetat e expresiei i execuia repetat a instruciunii ct timp (while) valoarea expresiei este diferit de zero (deci adevrat). Execuia ia sfrit n momentul n care valoarea expresiei este zero (fals); dac expresia are valoarea fals de la prima evaluare a expresiei, atunci instruciunea nu se execut deloc.Sintaxa instruciunii while prevede execuia repetat a unei singure instruciuni; dac dorim repetarea mai multor instruciuni, acestea vor fi descrise ca o instruciune compus (bloc), utiliznd n acest scop includerea lor ntre paranteze.Pentru a evita repetarea infinit a unui ciclu condiia de testat trebuie aleas cu grij; s considerm, de exemplu, secvena care elimin multiplii lui 2 dintr-un numr ntreg :while ( numar % 2 == 0 )numar = numar/2; /* sau: numar /= 2; */n acest exemplu expresia se modific n sensul terminrii ciclului, cu excepia cazului n care iniial numar=0, situaie n care ciclul se va repeta la infinit. Pentru a evita aceast situaie vom modific condiia astfel:while ( numar != 0 && numar %2 == 0 )numar = numar/2;/* numar/=2; */ Exemple:/*Programul determina cel mai mare divizor comun pentru doua numere a,b pozitive */#includemain(){ int a, b, rest; printf ("Introduceti doua numere intregi:\n"); scanf ("%d %d, &a, &b); while (b){ rest = a % b; a = b; b = rest; } printf ("Cel mai mare divizor este: %d\n", a);}

/*Media valorilor pozitive dintr-un sir de valori ce se termina cu 0 */#includemain(){double val, suma = 0;int nv = 0;printf ("Programul determina media numerelor pozitive\n");printf ("Introduceti numere (0 = sfarsit), numar=");scanf ("%lf", &val);while (val != 0){ if (val > 0){ nv++; suma += val; } printf ("numar = "); scanf ("%lf", &val); } /* while */ if(nv>0)printf ("Media valorilor pozitive este %5.2f", suma/nv); elseprintf ("Nu s-au introdus valori pozitive");}

/*Program ce citeste un numar (si cu parte fractionara) intr-o baza oarecare, cuprinsa intre 2 si 10 facandu-i apoi conversia in zecimal*/#include void main(){const char blanc = ' ', punct = '.', plus = '+', minus = '-';char semn, car;double valoare;int p_subunitar, baza;printf ("\nBaza=");scanf ("%d", &baza); while ( getchar() != '\n' );/* ultima instructiune are rolul de a descarca caracterul \n din intrare, altfel prima instructiune de citire (carcater sau sir de car.) va citi acest caracter *\printf ("\nIntroduceti numarul\n");car = blanc;while (car == blanc)scanf("%c", &car);semn = '+';if (car == plus || car == minus){semn = car;scanf ("%c", &car);};valoare = 0;while(car >= '0' && car < ('0'+baza)){ valoare = valoare*baza + car - '0'; scanf("%c", &car);}if (car == punct){p_subunitar = 0;scanf("%c", &car);while(car >= '0' && car < ('0'+baza)){ valoare = valoare*baza + car - '0'; scanf("%c", &car); p_subunitar++;}while (p_subunitar > 0){valoare /= baza;p_subunitar--;}}if (semn == minus)valoare = -valoare;printf("Valoarea zecimala este:%f\n", valoare);}

4.5.2. Instruciunea doSintaxa acestei instruciuni este:doinstruciune;while (expresie); Instruciunea din corpul ciclului poate fi simpl sau compus (bloc). Efectul acestei instruciuni const n execuia repetat a instruciunii din corpul ciclului (dintre do i while) i n evaluarea repetat a expresiei, ct timp (while) valoarea acesteia este adevrat (adic diferit de zero); execuia instruciuni se termina cnd valoarea devine fals adic egal cu zero. Exemple:/*Tipareste un numar intreg (de maxim 9-10 cifre) in ordine inversa*/#includemain(){long int numar, rest;printf ("Introduceti un numar intreg:");scanf ("%li",&numar);printf ("Numarul scris in ordine inversa:");do{rest=numar%10;printf("%d", rest);numar/=10;}while (numar);printf ("\n");}

/*Calculeaza pana la o limita specificata suma seriei:1 + 1/2 + 1/3 + 1/4 + . . . 1/n > limita programul va afisa fiecare suma si in final numarul de termeni insumati*/#include #define MAX_TERMENI100long int n = 0;long double suma = 0, limita;main(){printf ("Specificati limita: ");scanf ("%Lf", &limita);do{n ++;if ( n % 10 == 0 ) /* se afiseaza fiecare a 10-a iteratie */printf ("Pasul=%li\tSuma=%Lf\n", n, suma);suma += (long double) 1/n;}while (suma < limita && n < MAX_TERMENI);printf("Suma finala este : %Lf\n", suma );printf("Numarul de termeni insumati este: %li\n", n);}

/*Calculeaza radacina patrata a unui numar real, folosind sirul definit prin relatia de recurenta Xn=(Xn-1+a/Xn-1)/2, Xo=a/2*/#include #include #define MAX_TERMENI100main(){double radacina, a, precizia, modul;int n=0;printf ("Calculeaza radacina patrata a unui numar real\n");printf ("Introduceti numarul: ");scanf ("%lf", &a);if (a < 0)printf ("Nu se poate calcula radical dintr-un numar negativ\n");elseif (a == 0)printf ("Radacina este 0\n");else{radacina = a/2;/* initializare */precizia = a/1E+15;/*valoarea preciziei*/do{radacina = (radacina + a/radacina)/2;modul = a - radacina*radacina;if (modul < 0)modul = -modul;n++;}while ( modul > precizia && n < MAX_TERMENI);printf ("Radacina patrata din %lg este %lf obtinuta ""dupa %d iteratii\n", a, radacina, n);printf ("Valoarea returnata de functia standard sqrt ""este : %lf\n", sqrt(a));printf ("Diferenta fata de functia standard este %lg\n",sqrt(a)-radacina);}}

/* calculul lui e^x, utilizand dezvoltarea in serie Taylor:1 + x/1! + x^2/2! + x^3/3! + . . . + x^n/n! + . . . , cu o anumita precizie */#include #include main (){double ex, x, precizie, termen;intn=0;printf("Programul calculeaza exp(x); introduceti x=");scanf("%lf",&x);printf("\nCu precizia:");scanf("%lf", &precizie);ex = 1; termen = 1;do{n++;termen = termen * x / n;ex = ex + termen;}while ( termen > precizie );printf("seria Teylor exp(%f)=%f\n", x, ex);printf("Functia C exp(%f)=%f\n", x, exp(x));}

4.5.3. Instruciunea forAceast instruciune are urmtoarea sintaxa:for ( expr_iniializare ; condiie_ciclu ; expr_actualizare )instruciune;Efectul acestei instruciuni este urmtorul:-se evalueaz expr_iniializare o singur dat, la nceputul execuiei ciclului for; expr_iniializare poate fi o singur atribuire sau o list de expresii de atribuire separate prin virgule;

-apoi se evalueaz condiie_ciclu; dac valoarea sa este adevrat, deci diferit de zero, se execut instruciunea ce constituie corpul ciclului; dup aceasta se evalueaz expr_actualizare, care poate fi o singur expresie sau o list de expresii, separate prin virgule;

-aceast secven: execuie instruciune ciclu i apoi evaluare expr_actualizare continu ct timp valoarea condiie_ciclu este diferit de zero (adevrat); aceast expresie (condiie_ciclu) este evaluat de fiecare dat, nainte de execuia instruciunii ce constituie corpul ciclului;

-execuia ciclului ia sfrit cnd valoarea expresiei condiie_ciclu devine zero (fals).

Trebuie menionat c la fel ca la while, ciclul folosit poate s nu se execute de loc, dac de la prima evaluare expresia condiie_ciclu are valoarea fals.Aceasta instruciune poate fi descris si cu ajutorul instruciunii while:expr_iniializare;while (condiie_ciclu){instruciune;expr_actualizare; }Oricare dintre expresiile instruciunii for sau chiar toate pot lipsi. Dac lipsete conditie_ciclu, aceasta implic faptul c, clauza while (condiie_ciclu) este echivalent cu while (1), ceea ce nseamn o condiie permanent adevrat.Expr_actualizare poate conine una sau mai multe expresii ce sunt actualizate la fiecare ciclu; acestea sunt separate prin virgule.Exemple :/*Program ce afiseaza (genereaza) numerele prime in intervalul [3,n] intervalul este parcurs cu un pas egal cu 2, deoarece numerele prime sunt numai printre numerele impare*/#includevoid main(){long int n, i, div, este_prim;printf (" Afiseaza numerele prime pana la n=");scanf ("%ld", &n);printf ("\n%9d,%9d", 2, 3);for( i=5 ; i