Pagina Principală
Ora 7

Buclele CÂT TIMP și REPETĂ...PÂNĂ CÂND

Structuri repetitive cu test inițial și test final

40min teorie + 15min probleme PBInfo
Competența 3.2
Sigla liceului
TEORIE - 40 minute

Ce vei învăța astăzi?

După această lecție, vei stăpâni complet ambele tipuri de bucle cu număr necunoscut de pași și vei ști când să alegi fiecare dintre ele.

Sintaxa și funcționarea buclei CÂT TIMP (while)
Sintaxa și funcționarea buclei REPETĂ...PÂNĂ CÂND (do...while)
Diferențele dintre test inițial și test final
Când să folosești fiecare tip de buclă

Bucla CÂT TIMP (while)

Test INIȚIAL: verifică condiția înainte de a intra în buclă

Caracteristici:
  • Bucla poate să NU se execute deloc
  • Potrivită pentru validări și citiri controlate
  • Folosită când nu știi dacă trebuie să execuți

Sintaxa: ┌ cât timp (condiție) execută ... └■

Bucla REPETĂ...PÂNĂ CÂND (do...while)

Test FINAL: verifică condiția după ce a executat bucla

Caracteristici:
  • Bucla se execută CEL PUȚIN o dată
  • Potrivită pentru meniuri și procesări inițiale
  • Folosită când știi că trebuie să execuți cel puțin o dată

Sintaxa: ┌ repetă ... └■ până când (condiție)

1. Bucla CÂT TIMP (while) - Test Inițial

TEST INIȚIAL

Verifică ÎNAINTE de executare

EXECUTARE

Doar dacă condiția e adevărată

Definiție: Instrucțiunea while este o structură repetitivă cu număr necunoscut de pași și test inițial.

Mod de execuție:

Se evaluează Expresia
Rezultatul se convertește la bool
DA / NU
Adevărat sau Fals?
DA (true)
Se execută Instrucțiunea
Se reia pasul 1
NU (false)
Se trece după while

Exemplu practic: Suma primelor n numere

citește n S ← 0 i ← 1 ┌ cât timp i ≤ n execută │ S ← S + i │ i ← i + 1 └■ scrie S
Cod C++ echivalent
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int S = 0;
    int i = 1;
    
    while(i <= n) {
        S += i;
        i++;
    }
    
    cout << S << endl;
    return 0;
}

Rulați programul analizând rezultatul pentru diverse valori ale lui n, inclusiv 0.

Instrucțiunea se execută cât timp condiția este adevărată

Dacă condiția este falsă din start, instrucțiunea NU se execută deloc.

O singură instrucțiune

Instrucțiunea poate fi orice fel de instrucțiune, dar una singură. Pentru mai multe instrucțiuni, folosește instrucțiunea compusă (bloc cu { }).

Evită bucle infinite!

Este necesar ca cel puțin o variabilă care apare în condiție să-și modifice valoarea în instrucțiune. Altfel se obține o buclă infinită.

Exercițiu: Completează bucla while pentru validare
scrie "Introdu vârsta (0-120): "
______ varsta
______ varsta < 0 ______ varsta > 120 execută
│ scrie "Vârsta invalidă! Introdu din nou: "
______ varsta
└■
scrie "Vârsta validă: ", ______
Bancă de cuvinte:
citește cât timp sau varsta
💡 Atenție la TEST INIȚIAL: Dacă prima vârstă introdusă este validă (între 0-120), bucla nu se mai execută deloc!

2. Bucla REPETĂ...PÂNĂ CÂND (do...while) - Test Final

EXECUTARE

Mai întâi execută

TEST FINAL

Verifică DUPĂ executare

Definiție: Instrucțiunea do...while este o structură repetitivă cu număr necunoscut de pași și test final.

Mod de execuție:

Se execută Instrucțiunea
Se evaluează Expresia
Rezultatul se convertește la bool
DA / NU
Adevărat sau Fals?
DA (true)
Se reia de la început
NU (false)
Se trece după do...while

Exemplu practic: Suma primelor n numere (varianta)

citește n S ← 0 i ← 1 ┌ repetă │ S ← S + i │ i ← i + 1 └■ până când i > n scrie S

Diferență esențială: Bucla se execută cel puțin o dată, chiar și pentru n=0!

Cod C++ echivalent
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int S = 0;
    int i = 1;
    
    do {
        S += i;
        i++;
    }
    while(i <= n);
    
    cout << S << endl;
    return 0;
}

Rulați programul analizând rezultatul pentru diverse valori ale lui n, inclusiv 0. Observați diferența față de while!

Instrucțiunea se execută cel puțin o dată

Chiar dacă condiția este falsă din start, instrucțiunea se execută exact o dată.

O singură instrucțiune

La fel ca while, instrucțiunea poate fi orice fel de instrucțiune, dar una singură. Pentru mai multe instrucțiuni, folosește blocul.

Evită bucle infinite!

La fel ca while, este necesar ca cel puțin o variabilă din condiție să se modifice în corpul buclei.

Condiția inversă!

În do...while continuăm atâta timp cât condiția este adevărată. Atenție la inversarea logicii!

Exercițiu: Completează bucla do...while pentru meniu
optiune ← 0
______ # Începutul buclei do...while
│ scrie "Meniu:"
│ scrie "1. Adunare"
│ scrie "2. Scădere"
│ scrie "3. Ieșire"
│ citește ______ # Citim opțiunea utilizatorului
______ când ______ = 3 # Condiția de oprire (când utilizatorul alege 3)
scrie "La revedere!"
Bancă de cuvinte:
repetă până când optiune citește
💡 Perfect pentru meniuri: do...while este ideal pentru afișarea meniurilor - întotdeauna vrei să afișezi meniul cel puțin o dată!

Comparație detaliată: CÂT TIMP vs REPETĂ...PÂNĂ CÂND

Caracteristică CÂT TIMP (while) REPETĂ...PÂNĂ CÂND (do...while)
Tip test Test INIȚIAL Test FINAL
Execuție minimă 0 ori (poate să nu se execute deloc) 1 dată (se execută întotdeauna cel puțin o dată)
Când să folosești Validări, citiri până la marker, când nu ești sigur că trebuie să execuți Meniuri, procesări care trebuie să înceapă cel puțin o dată
Sintaxă Pseudocod ┌ cât timp (cond) execută ... └■ ┌ repetă ... └■ până când (cond)
Sintaxă C++ while(cond) { ... } do { ... } while(cond);
Logică condiție Continuă CÂT TIMP condiția este adevărată Repetă PÂNĂ CÂND condiția devine adevărată (oprește când e adevărată!)
Test de înțelegere: Care tip de buclă?

Pentru fiecare situație, alege tipul de buclă mai potrivit:

Poate că utilizatorul introduce 0 din prima → CÂT TIMP (test inițial)
Trebuie să afișezi meniul cel puțin o dată → REPETĂ...PÂNĂ CÂND (test final)
Poate că parola e corectă din prima → CÂT TIMP (test inițial)

Atenție la erorile comune!

1. Bucle infinite - uitarea de actualizare

❌ GREȘIT - buclă infinită:
i ← 1 ┌ cât timp i ≤ 5 execută │ scrie "Salut!" │ # AICI E PROBLEMA: nu mărim i! └■

Problemă: i rămâne întotdeauna 1, condiția i ≤ 5 este întotdeauna adevărată!

✅ CORECT - cu actualizare:
i ← 1 ┌ cât timp i ≤ 5 execută │ scrie "Salut!" │ i ← i + 1 # ACTUALIZARE OBLIGATORIE! └■

2. Confuzia logicii condiției

⚠️ Atenție la inversarea logicii:
While Do...While
while(x != 0) { ... } do { ... } while(x == 0);
Continuă cât timp x ≠ 0 Repetă până când x ≠ 0 (oprește când x ≠ 0)

Regulă: În do...while condiția este inversată față de while pentru același efect!

Best Practices pentru ambele bucle:

✅ Verifică întotdeauna dacă bucla poate începe/sfârși - testează cu valori limită (0, valori negative, etc.)
✅ Actualizează variabilele din condiție în fiecare iterație - altfel buclă infinită
✅ Alege tipul corect de buclă pentru situație - test inițial vs test final
✅ Documentează condiția de oprire - explică în comentarii când și de ce se oprește bucla
EXERCIȚII PBINFO - 15 minute

PbInfo #1220 - Suma cifrelor

Problemă perfectă pentru bucla while

Enunț:

Cerință: Să se scrie un program care citește un număr natural n și afișează suma cifrelor sale.

Date de intrare:

Programul citește de la tastatură numărul n.

Date de ieșire:

Programul va afișa pe ecran suma cifrelor lui n.

Exemplu:

Intrare:

12345

Ieșire:

15

Explicație: 1 + 2 + 3 + 4 + 5 = 15

Cum gândim soluția:
  1. Citim numărul n
  2. Pregătim o variabilă suma ← 0
  3. Cât timp n > 0 (test inițial - perfect pentru while):
    • Extragem ultima cifră: cifra ← n % 10
    • Adăugăm cifra la suma
    • Eliminăm ultima cifră: n ← n / 10 (actualizare importantă!)
  4. Afișăm suma
Urmărește pentru n=12345:
Iterația 1: n=12345, cifra=5, suma=5, n=1234
Iterația 2: n=1234, cifra=4, suma=9, n=123
Iterația 3: n=123, cifra=3, suma=12, n=12
Iterația 4: n=12, cifra=2, suma=14, n=1
Iterația 5: n=1, cifra=1, suma=15, n=0 → STOP
De ce while și nu do...while?

Pentru n=0 (număr cu o singură cifră, cifra 0):

  • While: condiția 0 > 0 este falsă → bucla nu se execută → suma=0 (corect!)
  • Do...while: s-ar executa cel puțin o dată → ar calcula greșit!
Scrie soluția în C++:
Soluție corectă:
#include <iostream>

using namespace std;

int main() {
    int n;
    cin >> n;
    
    int suma = 0;
    
    while (n > 0) {
        suma = suma + (n % 10);  // adaugă ultima cifră
        n = n / 10;              // elimină ultima cifră (ACTUALIZARE!)
    }
    
    cout << suma;
    
    return 0;
}

Ce am învățat din această problemă:

  • CÂT TIMP perfect pentru număr necunoscut de cifre
  • Actualizare obligatorie: n = n / 10 modifică variabila din condiție
  • Condiția corectă: n > 0 - când n devine 0, am terminat
  • Test inițial important: pentru n=0, bucla nu se execută (corect!)

Problemă cu do...while - Meniu interactiv

Exemplu perfect pentru do...while

Enunț:

Cerință: Să se scrie un program care afișează un meniu și execută operații până când utilizatorul alege să iasă.

Date de intrare:

Programul citește opțiuni de la tastatură până când se introduce 3.

Date de ieșire:

Programul afișează rezultatele operațiilor alese.

Exemplu de rulare:
Meniu:
1. Salut
2. La revedere  
3. Ieșire
Alege: 1
Salut!

Meniu:
1. Salut
2. La revedere
3. Ieșire
Alege: 2
La revedere!

Meniu:
1. Salut
2. La revedere
3. Ieșire
Alege: 3
Program terminat.
Cum gândim soluția:
  1. Pregătim o variabilă optiune ← 0
  2. Folosim do...while (test final - perfect pentru meniu):
    • Afișăm meniul (trebuie afișat cel puțin o dată)
    • Citim opțiunea
    • Executăm operația corespunzătoare
  3. Continuăm până când optiune = 3
De ce do...while și nu while?

Pentru că întotdeauna vrem să afișăm meniul cel puțin o dată, înainte de a întreba utilizatorul ce vrea să facă!

Scrie soluția în C++:
Soluție corectă:
#include <iostream>

using namespace std;

int main() {
    int optiune;
    
    do {
        // Afișăm meniul (se execută CEL PUȚIN o dată)
        cout << "Meniu:" << endl;
        cout << "1. Salut" << endl;
        cout << "2. La revedere" << endl;
        cout << "3. Ieșire" << endl;
        cout << "Alege: ";
        
        cin >> optiune;
        
        // Executăm operația corespunzătoare
        if (optiune == 1) {
            cout << "Salut!" << endl;
        } else if (optiune == 2) {
            cout << "La revedere!" << endl;
        } else if (optiune == 3) {
            cout << "Program terminat." << endl;
        } else {
            cout << "Opțiune invalidă!" << endl;
        }
        
        cout << endl;  // linie goală pentru claritate
        
    } while (optiune != 3);  // TEST FINAL: continuă până când optiunea este 3
    
    return 0;
}

Puncte cheie importante:

  • do...while perfect pentru meniuri - afișează întotdeauna meniul cel puțin o dată
  • Condiția inversată: while(optiune != 3) - continuă atâta timp cât nu am ales ieșirea
  • Actualizare în buclă: citirea opțiunii modifică variabila din condiție
  • Validare input: tratăm și cazul opțiunii invalide

Transformare Pseudocod → C++

Exercițiu de traducere pentru fixare

Pseudocod dat (numara cifrele pare ale lui n):

citește n numarPare ← 0 ┌ cât timp n > 0 execută │ cifra ← n % 10 │ ┌ dacă cifra % 2 = 0 atunci │ │ numarPare ← numarPare + 1 │ └■ │ n ← n / 10 └■ scrie numarPare

Ce face acest algoritm? Numără câte cifre pare are un număr.

Exemplu pentru n=246813: 2, 4, 6, 8 → 4 cifre pare

Transformă în C++ folosind while:
Soluție corectă:
#include <iostream>

using namespace std;

int main() {
    int n, numarPare = 0, cifra;
    
    cin >> n;
    
    while (n > 0) {
        cifra = n % 10;          // extragem ultima cifră
        
        if (cifra % 2 == 0) {    // verificăm dacă este pară
            numarPare++;         // incrementăm contorul
        }
        
        n = n / 10;              // eliminăm ultima cifră (ACTUALIZARE!)
    }
    
    cout << numarPare;
    
    return 0;
}

Observații importante pentru transformări Pseudocod → C++:

Pseudocod C++
┌ cât timp ... execută while (...) {
└■ }
=
% (rest) % (la fel)
scrie cout <<
citește cin >>
EXERCIȚII PRACTICE - 10 minute

Exercițiul Practic: Comparație între while și do...while

Sarcini de lucru

Completează următoarele sarcini pentru a-ți consolida înțelegerea diferențelor dintre cele două tipuri de bucle

Sarcina 1: Analiză comportament pentru n=0

Avem două algoritmi identici, unul cu while și unul cu do...while:

Algoritmul A (while):
citește n S ← 0 i ← 1 ┌ cât timp i ≤ n execută │ S ← S + i │ i ← i + 1 └■ scrie S
Algoritmul B (do...while):
citește n S ← 0 i ← 1 ┌ repetă │ S ← S + i │ i ← i + 1 └■ până când i > n scrie S
Soluție pentru Sarcina 1:

Analiza pentru n=0:

  • Algoritmul A (while):
    • Condiția: i ≤ n1 ≤ 0FALS
    • Bucla nu se execută deloc
    S rămâne 0 → afișează 0 (corect!)
  • Algoritmul B (do...while):
    • Bucla se execută cel puțin o dată
    • Adaugă 1 la S → S devine 1
    • Incrementează i → i devine 2
    • Verifică condiția: i > n2 > 0ADEVĂRAT
    Afișează 1 (greșit! suma primelor 0 numere este 0)
  • Concluzie: Algoritmul A (while) este corect pentru această problemă!
Sarcina 2: Scriere algoritm cu do...while

Cerință: "Scrieți un algoritm care cere utilizatorului să ghicească un număr secret (7). Utilizatorul introduce numere până când ghicește corect. Afișează de câte încercări a avut nevoie."

Exemplu de execuție:

Ghicește numărul secret: 3
Mai încearcă!
Ghicește numărul secret: 10  
Mai încearcă!
Ghicește numărul secret: 7
Corect! Ai ghicit din 3 încercări.
Soluție pentru Sarcina 2:
ALGORITMUL GhicesteNumar
VARIABILE
    numarSecret, incercare, contor: întreg
ÎNCEPUT
    numarSecret ← 7
    contor ← 0
    
    REPETĂ
        contor ← contor + 1
        SCRIE "Ghicește numărul secret: "
        CITESTE incercare
        
        DACĂ incercare ≠ numarSecret ATUNCI
            SCRIE "Mai încearcă!"
        SFÂRȘIT DACĂ
        
    PÂNĂ CÂND incercare = numarSecret
    
    SCRIE "Corect! Ai ghicit din ", contor, " încercări."
SFÂRȘIT

De ce do...while este perfect aici:

  1. Trebuie să cerem cel puțin o încercare (chiar dacă ar ghici din prima)
  2. Contorul începe de la 0 și crește în buclă
  3. Condiția inversată: continuă până când încercarea = numărul secret
  4. Perfect pentru jocuri și meniuri interactive
Sarcina 3: Conversie while ↔ do...while

Cerință: Transformă următorul algoritm while în echivalentul său do...while:

citește x ┌ cât timp x ≠ 0 execută │ scrie "Pătratul: ", x * x │ citește x └■ scrie "Terminat"
Soluție pentru Sarcina 3:
citește x ┌ repetă │ scrie "Pătratul: ", x * x │ citește x └■ până când x = 0 scrie "Terminat"

Reguli de conversie while ↔ do...while:

While Do...While Explicație
while(x != 0) do ... while(x == 0) Condiția se inversează!
Continuă cât timp condiția e adevărată Repetă până când condiția devine adevărată Logică diferită
Poate să nu se execute deloc Se execută cel puțin o dată Comportament diferit pentru x=0 inițial

Descarcă exercițiile