Invatare Atomica

Structuri de control — Master BAC

Progres lectie:
0%
🎯

Obiectivul lectiei

Recapitulezi complet if/else, for si while in C++ la nivel BAC intensiv: sintaxa exacta, urmarirea executiei pas cu pas cu tabel de valori, capcane clasice si bucle imbricate. Dupa aceasta lectie rezolvi orice exercitiu de tip „ce afiseaza?” fara sa calculezi gresit.

Dupa aceasta lectie vei putea:

  • Sa scrii corect sintaxa C++ pentru if/else if/else, for, while si do-while
  • Sa urmarest executia unui program pas cu pas completand un tabel de valori
  • Sa identifici conditia de intrare/iesire dintr-o bucla si sa calculezi numarul de iteratii
  • Sa recunosti capcanele clasice: bucla infinita, break/continue, off-by-one
  • Sa lucrezi cu bucle imbricate (tabel inmultire, numere prime)
  • Sa alegi structura de control potrivita pentru fiecare tip de problema BAC

Incearca singur!

Provocare de incalzire:

Ce afiseaza urmatorul fragment C++? Calculeaza manual inainte sa citesti lectia.

int a = 1, b = 0;
for (int i = 1; i <= 4; i++) {
    a = a + i;
    b = b + a;
}
cout << "a=" << a << " b=" << b;
💡 Ai nevoie de un indiciu?

Completeaza tabelul: pentru fiecare i (1..4), calculeaza mai intai a=a+i, apoi b=b+a.

Raspuns: a=11 b=24

1

1. Structura if / else if / else

Sintaxa generala C++:
  • if (conditie) — executa blocul daca conditia e adevarata (true / nenul)
  • else if (alta_conditie) — verificat NUMAI daca primul if a esuat
  • else — executat cand nicio conditie anterioara nu e adevarata
Regula importanta BAC: un singur else se leaga intotdeauna de cel mai apropiat if anterior fara else (dangling else).
Cod C++ rulat (g++ -std=c++17) — output real:
#include <iostream>
using namespace std;
int main() {
    // par / impar
    int x = 17;
    if (x % 2 == 0)
        cout << "par" << endl;
    else
        cout << "impar" << endl;
    // clasificare nota
    int nota = 8;
    if (nota >= 9)
        cout << "Excelent" << endl;
    else if (nota >= 7)
        cout << "Bine" << endl;
    else if (nota >= 5)
        cout << "Suficient" << endl;
    else
        cout << "Insuficient" << endl;
    return 0;
}
impar
Bine
Capcana dangling else (frecventa la BAC):
int a = 5, b = 3;
if (a > 0)
    if (b > 10)
        cout << "X";
else         // se leaga de if(b>10), NU de if(a>0)!
    cout << "Y";
Afiseaza Y: a>0 este adevarat, se intra in al doilea if, b>10 este fals, deci se executa else-ul aferent lui if(b>10).
2

2. Bucla for — sintaxa si variante

Sintaxa: for (initializare; conditie; actualizare) { corp; }
  • initializare — executata o singura data, la inceput
  • conditie — verificata INAINTE de fiecare iteratie; daca e falsa, bucla se opreste
  • actualizare — executata DUPA fiecare iteratie (chiar si daca continue a sarit corpul)
Numarul de iteratii pentru for(i=a; i<=b; i++): b − a + 1 iteratii.
Cod C++ rulat (g++ -std=c++17) — output real:
#include <iostream>
using namespace std;
int main() {
    // Suma numerelor de la 1 la 5
    int s = 0;
    for (int i = 1; i <= 5; i++) {
        s += i;
    }
    cout << "Suma 1..5 = " << s << endl;
    // Multipli de 3 intre 1 si 20
    for (int i = 1; i <= 20; i++) {
        if (i % 3 == 0)
            cout << i << " ";
    }
    cout << endl;
    // For cu pas negativ
    for (int i = 5; i >= 1; i--) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}
Suma 1..5 = 15
3 6 9 12 15 18
5 4 3 2 1 
Variante utile la BAC:
  • for(int i=0; i<n; i++) — parcurge indicii 0, 1, ..., n-1 (vectori indexati de la 0)
  • for(int i=1; i<=n; i+=2) — pas 2, numai numerele impare
  • for(;;) — bucla infinita (necesita break explicit)
Off-by-one (eroare clasica): i < n vs i <= n — diferenta de o iteratie; la BAC apar ambele variante pentru a te incurca.
3

3. Bucla while si do-while

while (conditie) { corp; } — conditia verificata inainte; daca e falsa de la inceput, corpul nu se executa deloc. Folosit cand nu stim dinainte numarul de iteratii.

do { corp; } while (conditie); — corpul se executa cel putin o data, apoi se verifica conditia. Folosit la validare intrari si meniuri.
Cod C++ rulat (g++ -std=c++17) — output real:
#include <iostream>
using namespace std;
int main() {
    // while: extrage cifrele lui 1234 de la dreapta
    int n = 1234;
    cout << "Cifrele lui " << n << " (dreapta): ";
    while (n > 0) {
        cout << n % 10 << " ";
        n /= 10;
    }
    cout << endl;
    // do-while: simuleaza validare cu incercari 10, 25, 42
    int secret = 42;
    int inc[] = {10, 25, 42};
    int idx = 0, tentativa = 0, ghicit;
    do {
        ghicit = inc[idx++];
        tentativa++;
        if (ghicit != secret)
            cout << "Gresit! Mai incearca." << endl;
    } while (ghicit != secret);
    cout << "Corect! Ai ghicit in " << tentativa << " incercari." << endl;
    return 0;
}
Cifrele lui 1234 (dreapta): 4 3 2 1
Gresit! Mai incearca.
Gresit! Mai incearca.
Corect! Ai ghicit in 3 incercari.
Algoritmul extragerii cifrelor — esential la BAC:
  • n % 10 → ultima cifra
  • n / 10 → elimina ultima cifra (impartire intreaga)
  • Repeti cat timp n > 0
Cand alegi while vs for? Daca numarul de iteratii e necunoscut inainte (depinde de date), alege while. Daca stii sigur de cate ori se repeta, alege for.
4

4. Urmarirea executiei — tehnica tabelului de valori

La BAC Subiectul I apar constant exercitii „ce afiseaza programul?”. Tehnica corecta: construiesti un tabel de valori cu o coloana pentru fiecare variabila si o linie pentru fiecare iteratie. Calculezi in ordine, linie cu linie.
Exemplul 1: bucla FOR cu doua variabile (output verificat g++):
int a = 1, b = 0, i;
for (i = 1; i <= 4; i++) {
    a = a + i;
    b = b + a;  // b foloseste NOUL a, nu vechiul!
}
cout << "a=" << a << " b=" << b;
a=11 b=24
Tabelul de urmarire (scris pe foaie la examen):
|  i  |  a (a+i)   |  b (b+a)   |
|-----|------------|------------|
|  1  | 1+1 =  2   | 0+2  =  2  |
|  2  | 2+2 =  4   | 2+4  =  6  |
|  3  | 4+3 =  7   | 6+7  = 13  |
|  4  | 7+4 = 11   | 13+11= 24  |
Rezultat: a=11, b=24
Exemplul 2: numara cifrele pare din 2846 (output verificat g++):
int n = 2846, cnt = 0;
while (n > 0) {
    if ((n % 10) % 2 == 0)
        cnt++;
    n /= 10;
}
cout << "Cifre pare in 2846: " << cnt;
Cifre pare in 2846: 4
Urmarire while (2846) pas cu pas:
|   n  | n%10 | par? | cnt | n/=10 |
|------|------|------|-----|-------|
| 2846 |  6   |  DA  |  1  |  284  |
|  284 |  4   |  DA  |  2  |   28  |
|   28 |  8   |  DA  |  3  |    2  |
|    2 |  2   |  DA  |  4  |    0  |
Conditia 0>0 falsa: STOP. cnt=4
5

5. break, continue si bucle imbricate

  • break — iese imediat din bucla curenta (nu din toate buclele imbricate!)
  • continue — sare la urmatoarea iteratie (la for: executa actualizarea, la while: reevalueaza conditia)
Cod C++ rulat (g++ -std=c++17) — output real:
#include <iostream>
using namespace std;
int main() {
    // break: opreste la primul multiplu de 7
    for (int i = 1; i <= 50; i++) {
        if (i % 7 == 0) {
            cout << "Primul multiplu de 7: " << i << endl;
            break;
        }
    }
    // continue: afiseaza numerele impare 1-10
    cout << "Impare 1-10: ";
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) continue;
        cout << i << " ";
    }
    cout << endl;
    return 0;
}
Primul multiplu de 7: 7
Impare 1-10: 1 3 5 7 9 
Bucle imbricate: tabel inmultire 3x3 + numere prime pana la 20 (output real):
#include <iostream>
using namespace std;
int main() {
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++) {
            cout << i * j;
            if (j < 3) cout << "	";
        }
        cout << endl;
    }
    cout << "---" << endl;
    int count = 0;
    for (int n = 2; n <= 20; n++) {
        bool prim = true;
        for (int d = 2; d * d <= n; d++) {
            if (n % d == 0) { prim = false; break; }
        }
        if (prim) { cout << n << " "; count++; }
    }
    cout << endl;
    cout << "Numere prime pana la 20: " << count << endl;
    return 0;
}
1	2	3
2	4	6
3	6	9
---
2 3 5 7 11 13 17 19
Numere prime pana la 20: 8
Regula break in bucle imbricate: break iese NUMAI din bucla in care se afla. Daca vrei sa iesi din 2 bucle, folosesti o variabila flag (bool gasit = false;) si un if suplimentar.
6

6. Capcane clasice BAC si ghid de alegere a structurii

Cele mai frecvente capcane la Subiectul I:
Capcana 1: Bucla infinita
// int x=3; while(x!=0) x=x+2;
// x=3,5,7,9,... mereu impar, nu devine 0 => INFINIT!
// Corectie: while(x < 20) x=x+2; sau while(x!=0) x=x-1;
Capcana 2: Off-by-one (< vs <=)
int s1=0;
for(int i=1;i<10;i++) s1+=i;  // intentionam 1..10, dar i<10 omite pe 10: s1=45 (in loc de 55)
int s2=0;
for(int i=1;i<=10;i++) s2+=i; // CORECT: s2=55
Capcana 3: Modificarea variabilei de control (output: 1 3 5 7 9)
for(int i=0;i<10;i++) {
    if(i%2==0) i++;
    cout<<i<<" ";
} // i=0->1; i=2->3; i=4->5; i=6->7; i=8->9; STOP
Ghid de alegere a structurii (pentru BAC):
  • if — decizie unica, fara repetitie
  • for — numar de iteratii cunoscut dinainte
  • while — numarul de iteratii depinde de date
  • do-while — minimum o executie garantata

Exercitii practice

Exercitiul 1 (Nivel minim)

Ce afiseaza: int x=0, y=1; for(int i=1; i<=5; i++) { x=x+i; y=y*i; } cout << x << " " << y;

Construieste un tabel cu coloanele i, x, y si indica valorile finale.

Exercitiul 2 (Nivel standard)

Scrie un program C++ care citeste n si afiseaza toti divizorii sai proprii (fara 1 si n). Daca nu are, afiseaza „Numar prim”.

Verifica: n=12 afiseaza 2 3 4 6; n=7 afiseaza „Numar prim”.

Exercitiul 3 (Nivel performanta)

Analizeaza: int n=100, s=0, i=1; while(i*i <= n) { if(n%i==0) s+=i; i++; } cout << s;

  1. Ce calculeaza algoritmul pentru n=100?
  2. Cate iteratii executa bucla while pentru n=100?
  3. Ce afiseaza pentru n=100 si n=36?
  4. De ce i*i <= n este mai eficienta decat i <= n?

Ce ai consolidat astazi

  • if/else if/else — sintaxa exacta, dangling else, conditii compuse
  • for — numar iteratii = b-a+1; pas variabil; off-by-one
  • while — conditie inainte; algoritmul cifrelor
  • do-while — executie garantata cel putin o data
  • Tabelul de urmarire — tehnica corecta la BAC
  • Capcane: bucla infinita, off-by-one, break din bucla curenta, continue executa actualizarea
  • Bucle imbricate — tabel inmultire, numere prime

Urmatoarea lectie

Continua cu Vectori si Matrice — Complet.

Continua →