Structurile repetitive permit executarea unei secvențe de instrucțiuni atât timp cât o condiție rămâne adevărată. Cele trei forme din C/C++ sunt echivalente ca putere de calcul, dar fiecare exprimă mai natural un anumit tip de repetiție.
1Obiectivele lucrării
- Alegerea buclei potrivite în funcție de problema de rezolvat
- Înțelegerea diferenței dintre buclele cu test inițial și cele cu test final
- Construirea corectă a celor trei componente ale instrucțiunii
for - Utilizarea instrucțiunilor
breakșicontinue - Identificarea și evitarea buclelor infinite
2Cele trei bucle, comparate
| Instrucțiune | Testul condiției | Execuții minime | Se folosește când |
|---|---|---|---|
while | înainte de corp | 0 | numărul de repetări nu este cunoscut dinainte |
do-while | după corp | 1 | corpul trebuie executat măcar o dată (meniuri, validări) |
for | înainte de corp | 0 | numărul de repetări este cunoscut sau se parcurge un interval |
3Instrucțiunile while și do-while
while (expresie)
instructiune;
do
instructiune;
while (expresie); // atentie: punct si virgula obligatoriu aici
La while se testează întâi expresia; dacă este adevărată (nenulă), se execută corpul,
apoi se reevaluează. La do-while, corpul se execută înainte de primul test, deci
cel puțin o dată, indiferent de condiție.
4Instrucțiunea for
for (initializare; conditie; pas)
instructiune;
for (int i = 0; i < 10; i++) { ... }
│ │ └── se executa DUPA fiecare iteratie
│ └─────────── se testeaza INAINTE de fiecare iteratie
└─────────────────────── se executa O SINGURA DATA, la inceput
Toate cele trei componente sunt opționale. for (;;) este o buclă infinită validă,
echivalentă cu while (1).
| Formă | Efect |
|---|---|
for (i = 0; i < n; i++) | parcurgere crescătoare clasică |
for (i = n - 1; i >= 0; i--) | parcurgere descrescătoare |
for (i = 0, j = n; i < j; i++, j--) | doi indici, folosind operatorul virgulă |
for (;;) | buclă infinită |
5Simulator de bucle
Modificați cei trei parametri și urmăriți tabelul de iterații: de câte ori se execută corpul, ce valori ia contorul și cu ce valoare rămâne după terminarea buclei. Puneți pasul pe 0 pentru a vedea cum se detectează o buclă infinită.
6Execuție pas cu pas
Urmăriți cum funcționează continue și break într-o buclă
care însumează doar numerele pare, oprindu-se la prima valoare negativă.
7Instrucțiuni de salt
| Instrucțiune | Efect | Domeniu de acțiune |
|---|---|---|
break | părăsește bucla sau switch-ul curent | doar structura cea mai interioară |
continue | sare la următoarea iterație | doar bucla cea mai interioară |
return | părăsește funcția, returnând o valoare | întreaga funcție |
goto eticheta | salt necondiționat la o etichetă | în interiorul aceleiași funcții |
exit(cod) | termină întreg programul | tot programul |
goto face codul greu de urmărit
și de întreținut. Singura utilizare acceptată în practica modernă este ieșirea rapidă din bucle imbricate
adânc, către un punct comun de eliberare a resurselor.break iese doar din bucla interioară.
Pentru a părăsi ambele bucle, se folosește un indicator (bool gasit), se scoate codul
într-o funcție cu return, sau - rar - goto.8Erori frecvente
for (i = 0; i < 10; i++); execută bucla de zece ori „în gol", iar blocul de dedesubt
se execută o singură dată.for (i = 0; i <= n; i++) execută n + 1 iterații. La parcurgerea unui tablou cu
n elemente, aceasta depășește limita cu o poziție.do-while, continue sare direct la testul condiției. Dacă incrementarea
contorului se afla după continue, ea nu se mai execută și bucla devine infinită.for face comportamentul greu de urmărit
și este o sursă frecventă de bucle care nu se termină.9Cod sursă
#include <stdio.h>
int main(void)
{
int n, i = 0;
double valoare, suma = 0.0;
printf("Cate valori? ");
scanf("%d", &n);
while (i < n) {
printf("Valoarea %d: ", i + 1);
scanf("%lf", &valoare);
suma += valoare;
i++; // FARA aceasta linie: bucla infinita
}
if (n > 0)
printf("Media aritmetica = %.4f\n", suma / n);
else
printf("Nicio valoare introdusa\n");
return 0;
}
#include <stdio.h>
int main(void)
{
int optiune;
do {
printf("\n--- MENIU ---\n");
printf("1. Adauga\n2. Sterge\n3. Afiseaza\n0. Iesire\n");
printf("Alegeti: ");
scanf("%d", &optiune);
switch (optiune) {
case 1: printf("Ati ales adaugarea\n"); break;
case 2: printf("Ati ales stergerea\n"); break;
case 3: printf("Ati ales afisarea\n"); break;
case 0: printf("La revedere!\n"); break;
default: printf("Optiune invalida\n");
}
} while (optiune != 0); // meniul se afiseaza macar o data
return 0;
}
#include <stdio.h>
#include <math.h>
int estePrim(int n)
{
if (n < 2) return 0;
for (int d = 2; d <= (int)sqrt(n); d++)
if (n % d == 0)
return 0; // iesire imediata din functie
return 1;
}
int main(void)
{
printf("Numerele prime pana la 50:\n");
for (int n = 1; n <= 50; n++) {
if (!estePrim(n)) continue; // sare peste cele neprime
printf("%d ", n);
}
printf("\n");
// tabla inmultirii, cu bucle imbricate
printf("\nTabla inmultirii 1-5:\n");
for (int i = 1; i <= 5; i++) {
for (int j = 1; j <= 5; j++)
printf("%4d", i * j);
printf("\n"); // linie noua dupa fiecare rand
}
return 0;
}
10Atelier de cod
La bucle, modul Pas cu pas este cel mai util instrument: vedeți contorul crescând și condiția fiind reevaluată la fiecare trecere.
11Sarcini de lucru
- Calculați media aritmetică a N valori citite de la tastatură, folosind
while. - Rescrieți același program cu
forși apoi cudo-while; comparați lizibilitatea. - Implementați un meniu repetitiv care se închide doar la alegerea opțiunii 0.
- Afișați toate numerele prime până la 100, folosind
continue. - Generați tabla înmulțirii cu bucle imbricate și aliniere pe coloane.
- Calculați suma cifrelor unui număr introdus, folosind
while. - Reproduceți eroarea „off by one" la parcurgerea unui tablou și observați ce se afișează.
- Scrieți o buclă care caută o valoare într-o matrice și iese din ambele bucle la prima potrivire.
12Aplicație de aprofundare
int.