Bucle - While si For
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)
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 (;;)
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 canti-
tati 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;
}
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[];
}
Virgulele care separa argumentele functiilor, variabilele
din declaratii, etc nici nu sint operatori "virgula" si nu garan-
teaza evaluarea de la stinga la dreapta.
Exercitiul 3.2. Scrieti o functie expand(s1, s2) care expa-
ndeaza 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).