Capitolul 3.5. WHILE si FOR

Vezi subiectul anterior Vezi subiectul urmator In jos

Capitolul 3.5. WHILE si FOR

Mesaj  zooky la data de Mier Mar 18, 2009 12:12 pm

Am intilnit deja buclele while si for. In

while (expresie)
instructiune

"expresie" este evaluata. Daca ea este nenula, "instructiune" este executata si "expresie" este reevaluata. Acest ciclu continua atita timp cit "expresie" nu este zero, iar cind ea devine zero executia se reia de dupa "instructiune".
Instructiunea for:

for (expr1; expr2; expr3)
instructiune

este echivalenta cu

expr1;
while (expr2) {
instructiune
expr3;
}

Din punct de vedere gramatical, cele trei componente ale unei bucle for sint expresii. In majoritatea cazurilor, expr1 si expr3 sint asignari sau apeluri de functii iar expr2 este o expresie relationala. Oricare din cele trei parti poate fi omisa, cu toate ca punct-virgula corespunzatoare trebuie sa ramina. Daca expr1 sau expr3 este lasata afara, i nu mai este incrementat. Daca testul, expr2 nu este prezent, el este luat ca fiind permanent adevarat, asa incit:

for (;; ) {
...
{

este o bucla infinita, si probabil de spart cu alte mijloace (ca de exemplu, un break sau return).
Folosirea lui while sau a lui for este in mare masura un subiect de gust. De exemplu, in:

while ((c = getchar()) == ' ' || c == '\n' || c == '\t')
; /* sari caracterele de spatiere */

nu exista nici o initializare sau reinitializare, asa ca while pare cea mai naturala.
Bucla for este clar superioara atunci cind exista o simpla initializare si reinitializare, deoarece ea pastreaza instructiunile de control al buclei impreuna si la loc vizibil in virful buclei. Acest lucru este cel mai evident in:

for (i = 0; i < N; i++)

care este varianta in C pentru prelucrarea primelor N elemente dintr-un tablou, analog cu bucla DO din FORTRAN si PL/1. Cu toate acestea, analogia nu este perfecta, deoarece limitele unei bucle for pot fi alterate din interiorul buclei si variabila de control i isi pastreaza valoarea cind bucla se termina, indiferent cum. Deoarece componentele unei bucle for sint expresii arbitrare, buclele for nu sint limitate la progresii aritmetice. Cu toate acestea, este un prost stil de programare acela de a forta calcule neinrudite intr-o bucla for; mai bine rezervati-le pentru operatiile de control ale buclei.
Ca un exemplu mai mare, iata o alta versiune a functiei atoi pentru convertirea unui sir in echivalentul sau numeric. Acest exemplu este mai general; el opereaza cu blancuri optionale nesemnificative si cu semn optional +/-. (Capitolul 4 va descrie functia atof care face aceeasi conversie pentru numere flotante).
Structura de baza a programului reflecta forma intrarii:

sari peste spatiile albe , daca exista
ia semnul, daca exista
ia partea intreaga, converteste-o

Fiecare pas isi face partea lui si lasa lucrurile intr-o stare curata pentru urmatorul. Intregul proces se termina la primul caracter care nu poate fi parte a unui numar.

atoi(s) /* converteste pe s in intreg */
char s[];
{
int i, n, sign;
for (i = 0; s[i] ==' ' || s[i] =='\n' || s[i] == '\t';i++)
; /* sari spatiile albe */
sign = 1;
if (s[i] == '+' || s[i] == '-') /* semnul */
sign = (s[i++] == '+') ? 1 : -1;
for (n = 0; s[i] >= '0' && s[i] <= '9'; i++)
n = 10 * n + s[i] - '0';
return(sign * n)
}

Avantajul pastrarii centralizate a controlului buclei este si mai clar atunci cind exista mai multe bucle imbricate. Urmatoarea functie este o sortare shell pentru un tablou de intregi. Ideea de baza a sortarii shell este aceea ca in stadiile de inceput se compara elemente indepartate si nu cele adiacente, ca in sortarile simple bazate pe interschimbare. Aceasta tinde sa elimine cantitati mari de dezordine, rapid, asa ca stadiile urmatoare au mai putin de lucru. Intervalul dintre elementele comparate scade treptat spre unu, punct in care sortarea devine efectiv o metoda de interschimbare adiacenta.

shell(v, n) /* sorteaza v[0], ...,v[n-1] in ordine crescatoare */
int v[], n;
{
int gap, i, j, temp;
for (gap = n / 2; gap > 0; gap /= 2)
for (i = gap; i < n; i++)
for (j = i - gap; j>= 0 && v[j] > v[j+gap]; j -= gap){
temp = v[j];
v[j] = v[j + gap];
v[j + gap] = temp;
}
}

Sint aici trei bucle imbricate. Cea mai dinafara contoleaza distanta dintre elementele comparate, contractind-o de la n/2 prin injumatatire la fiecare pas, pina cind devine zero. Bucla din mijloc compara fiecare pereche de elemente care este separata de un "gap"; bucla cea mai din interior le inverseaza pe acele elemente care nu sint in ordine. Deoarece "gap" poate fi redus la 1 eventual, toate elementele sint eventual ordonate corect. Sa notam ca generalitatea lui "for" face ca bucla exterioara sa aiba aceeasi forma ca celelalte, chiar daca nu este o progresie aritmetica.
Un operator final in limbajul C este virgula "," care isi gaseste adesea utilizare in instructiunea for. O pereche de expresii separate printr-o virgula este evaluata de la stinga spre dreapta si tipul si valoarea rezultatului sint tipul si valoarea operandului din dreapta. Astfel, intr-o instructiune for este posibil sa plasam expresii multiple in parti variate, de exemplu sa prelucram doi indici in paralel. Acest lucru este ilustrat de functia reverse(s) care inverseaza pe loc un sir s.

reverse(s) /* inverseaza pe loc sirul s */
char s[];
{
int c, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

Virgulele care separa argumentele functiilor, variabilele din declaratii, etc nici nu sint operatori "virgula" si nu garanteaza evaluarea de la stinga la dreapta.

Exercitiul 3.2. Scrieti o functie expand(s1, s2) care expandeaza notatiile scurte de tipul a-z in sirul s1 in lista echivalenta si completa abc....xyz in s2. Sint permise litere mari si mici si cifre; sa fiti pregatiti sa tratati si cazuri de tipul a-b-c si a-z0-9 si -a-z. (O conventie utila este aceea ca "-"la inceput este considerat ca atare).
avatar
zooky
Moderator
Moderator

Numarul mesajelor : 147
Data de inscriere : 15/03/2009
Varsta : 24
Localizare : Cernatesti City

Vezi profilul utilizatorului http://e-learning.forumhit.ro

Sus In jos

Vezi subiectul anterior Vezi subiectul urmator Sus


 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum