Structura repetitivă

Bază~16 min10 pași

De ce contează?

Când numeri pașii pe scări — „unu, doi, trei..." — repeți aceeași acțiune (urci o treaptă, crești numărătoarea) până ajungi sus. O buclă în program face exact asta: repetă un set de instrucțiuni până când o condiție îți spune să te oprești.

De ce avem nevoie de bucle

Imaginează-ți că vrei să aduni 1000 de numere. Fără bucle, ai scrie 1000 de linii. Cu o structură repetitivă, scrii instrucțiunea o dată și o repeți automat. Bucla e ce transformă un program scurt într-unul care prelucrează volume mari de date.

Bucla for — când știi de câte ori

Folosește for când cunoști numărul de repetări. Are trei părți:

for (int i = 0; i < n; i++) {
    // corpul buclei
}
  • int i = 0 — inițializare (o singură dată, la început).
  • i < n — condiția: cât timp e adevărată, bucla continuă.
  • i++ — pasul: crește i după fiecare repetare.

Suma primelor n numere naturale:

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    long long suma = 0;          // long long: suma poate fi mare
    for (int i = 1; i <= n; i++) {
        suma += i;               // suma = suma + i
    }
    cout << suma << "\n";
    return 0;
}

Pentru n = 5: i ia pe rând 1, 2, 3, 4, 5, iar suma devine 1, 3, 6, 10, 15.

Cum „avansează" indicele printr-un vector

Cea mai frecventă folosire a lui for e parcurgerea unui vector. Indicele i mută „reflectorul" peste celule, de la stânga la dreapta:

v
5
3
8
1
9
i
0
1
2
3
4
i
La pasul i = 2, bucla privește celula v[2] = 8. La pasul următor i devine 3 și reflectorul se mută o poziție la dreapta.
int v[] = {5, 3, 8, 1, 9};
int n = 5;
for (int i = 0; i < n; i++) {
    cout << v[i] << " ";     // 5 3 8 1 9
}
Observația-cheie

Indicii unui vector cu n elemente merg de la 0 la n−1. De aceea condiția corectă e i < n, nu i <= n. Cu i <= n ai accesa v[n], o celulă care nu există.

Bucla while — când te oprești pe o condiție

Folosește while când nu știi numărul de pași, ci doar condiția de oprire. Numărul de cifre ale unui număr:

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int cifre = 0;
    while (n > 0) {
        n = n / 10;      // taiem ultima cifra
        cifre++;
    }
    cout << cifre << "\n";
    return 0;
}

Pentru n = 2024: n devine 202 → 20 → 2 → 0, iar cifre ajunge la 4. Nu știam dinainte câți pași facem — depinde de număr.

Observația-cheie

Orice while are nevoie de un pas care apropie condiția de fals (aici n = n / 10). Fără el, condiția rămâne adevărată la nesfârșit → buclă infinită.

Complexitate

StructurăRepetăriTimp
for (i=0; i<n; i++)nO(n)
două bucle imbricaten · nO(n²)
while (n > 0) n /= 10~log₁₀(n)O(log n)

Numărul de repetări dictează complexitatea. O buclă în alta peste n elemente dă O(n²) — atenție la timp pentru n mare.

Greșeli frecvente

Greșeli reale cu buclele:

  • Off-by-one: i <= n în loc de i < n accesează v[n], care nu există → rezultat greșit sau crash.
  • Buclă infinită: uiți i++ (la for, în corpul unui while) sau pasul nu schimbă condiția → programul nu se mai termină, depășești timpul.
  • Variabilă resetată în buclă: declari int maxim = 0; înăuntrul buclei → se resetează la fiecare pas. Declar-o înainte.
  • Acumulare în int: o sumă de multe valori se sparge; folosește long long.

De reținut

  • for când știi numărul de pași; while când te oprești pe o condiție.
  • Indicii unui vector merg 0..n−1 → condiția corectă e i < n.
  • Numărul de repetări fixează complexitatea; orice while are nevoie de un pas spre oprire.

Întrebarea 1 / 3

Câte ori se execută corpul buclei `for (int i = 0; i < n; i++)` pentru n = 5?