Ce vei învăța astăzi?
După această lecție, vei putea verifica diverse proprietăți ale elementelor dintr-un vector folosind flag-uri și condiții logice.
Ce este un FLAG (steguleț)?
Definiție: Un flag este o variabilă booleană (adevărat/fals) care indică prezența sau absența unei proprietăți.
Analogii:
✓ Steguleț ridicat = proprietatea este adevărată
✓ Steguleț coborât = proprietatea este falsă
✓ Comutator aprins/stins = stare activă/inactivă
DEMONSTRAȚIE FLAG
Analogii pentru a înțelege flag-urile:
În repaus: flag = FALS. Când detectează fum: flag = ADEVĂRAT.
Profesorul pornește cu flag = ADEVĂRAT. Când găsește un elev fără teme: flag = FALS.
Începi cu flag = FALS. Când le găsești: flag = ADEVĂRAT.
Prima întrebare corectă: „Toate?”, „Există?”, „Niciunul?”
Înainte să scrii cod, alege întrebarea potrivită. În informatică, aproape orice verificare pe vector se reduce la una din aceste 3 forme:
- TOATE elementele au proprietatea P?
- EXISTĂ cel puțin un element cu proprietatea P?
- NICIUN element nu are proprietatea P?
| Întrebare | Cum pornești flag-ul | Ce cauți în buclă | Te oprești când... |
|---|---|---|---|
| TOATE au P? | true |
un contraexemplu (un element care NU are P) | ai găsit primul element care NU are P |
| EXISTĂ un element cu P? | false |
un exemplu (un element care ARE P) | ai găsit primul element care ARE P |
| NICIUN element nu are P? | true |
un contraexemplu (un element care ARE P) | ai găsit primul element care ARE P |
Truc logic foarte util: „Niciun element nu e 0” este același lucru cu „Toate elementele sunt diferite de 0”.
// 1) TOATE au P? -> pornesc true, caut contraexemplu
bool ok = true;
for (int i = 0; i < n; i++) {
if ( /* v[i] NU are P */ ) {
ok = false;
break;
}
}
// 2) EXISTĂ cu P? -> pornesc false, caut exemplu
bool gasit = false;
for (int i = 0; i < n; i++) {
if ( /* v[i] ARE P */ ) {
gasit = true;
break;
}
}
// 3) NICIUN cu P? -> pornesc true, caut contraexemplu (un element cu P)
bool ok2 = true;
for (int i = 0; i < n; i++) {
if ( /* v[i] ARE P */ ) {
ok2 = false;
break;
}
}
Algoritmi pentru verificarea proprietăților
Strategie: Începem cu presupunerea că proprietatea este adevărată (ok = true). Dacă găsim un contraexemplu, schimbăm flag-ul în false.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
// Citire vector
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// Verificare: toate elementele sunt pare?
bool toatePare = true; // Flag - presupunem că toate sunt pare
for (int i = 0; i < n; i++) {
if (v[i] % 2 != 0) { // Dacă găsim un număr impar
toatePare = false; // Atunci nu mai sunt toate pare
break; // Ieșim din buclă (optimizare)
}
}
if (toatePare) {
cout << "TOATE elementele sunt pare." << endl;
} else {
cout << "NU toate elementele sunt pare." << endl;
}
return 0;
}
Strategie inversă: Începem cu presupunerea că proprietatea este falsă (gasit = false). Dacă găsim un exemplu, schimbăm flag-ul în true.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
// Citire vector
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// Verificare: există cel puțin un element par?
bool existaPar = false; // Flag - presupunem că nu există
for (int i = 0; i < n; i++) {
if (v[i] % 2 == 0) { // Dacă găsim un număr par
existaPar = true; // Atunci am găsit cel puțin unul
break; // Ieșim din buclă (optimizare)
}
}
if (existaPar) {
cout << "EXISTĂ cel puțin un element par." << endl;
} else {
cout << "NU există niciun element par." << endl;
}
return 0;
}
Observație: "Niciun element nu are proprietatea X" este logic echivalent cu "Toate elementele NU au proprietatea X".
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
// Citire vector
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// Verificare: niciun element nu este negativ?
bool niciunNegativ = true; // Flag - presupunem că niciunul nu e negativ
for (int i = 0; i < n; i++) {
if (v[i] < 0) { // Dacă găsim un număr negativ
niciunNegativ = false; // Atunci avem cel puțin un negativ
break; // Ieșim din buclă
}
}
if (niciunNegativ) {
cout << "NICIUN element nu este negativ." << endl;
} else {
cout << "Există cel puțin un element negativ." << endl;
}
return 0;
}
Aici ai „traducerea” pe care o folosim la clasă: întâi pseudocod (pașii), apoi varianta C++ (de copiat și rulat).
bool ok = true;
for (int i = 0; i < n; i++) {
if (v[i] % 2 != 0) { // contraexemplu: impar
ok = false;
break;
}
}
cout << (ok ? "DA" : "NU");
bool gasit = false;
for (int i = 0; i < n; i++) {
if (v[i] % 2 == 0) { // exemplu: par
gasit = true;
break;
}
}
cout << (gasit ? "DA" : "NU");
bool ok = true;
for (int i = 0; i < n; i++) {
if (v[i] == 0) { // contraexemplu: am găsit 0
ok = false;
break;
}
}
cout << (ok ? "DA" : "NU");
Observă că „oprește” din pseudocod devine break; în C++.
Îl folosim ca să nu parcurgem degeaba restul vectorului.
Rețetele standard (exact ca în problemele de tip „DA/NU”)
Când verifici o proprietate într-un vector, alegi una din cele 3 întrebări: „toate?”, „există?”, „niciunul?”. Diferența dintre ele este valoarea inițială a flag-ului și condiția care îl schimbă.
| Întrebare | Flag inițial | Când îl schimb? | Ce caut? |
|---|---|---|---|
| Toate elementele au proprietatea P? | true |
când găsesc un element care NU are P | contraexemplu |
| Există cel puțin un element cu P? | false |
când găsesc un element care ARE P | exemplu |
| Niciun element nu are P? | true |
când găsesc un element care ARE P | contraexemplu |
bool ok = true;
for (int i = 0; i < n; i++) {
if ( /* v[i] NU are proprietatea P */ ) {
ok = false;
break;
}
}
bool gasit = false;
for (int i = 0; i < n; i++) {
if ( /* v[i] ARE proprietatea P */ ) {
gasit = true;
break;
}
}
bool ok = true;
for (int i = 0; i < n; i++) {
if ( /* v[i] ARE proprietatea P */ ) {
ok = false;
break;
}
}
Truc: dacă întrebarea e de tip „DA/NU”, aproape sigur ai un flag + o singură parcurgere.
Folosește break când ai aflat răspunsul, ca să nu muncești degeaba.
Greșeli care apar foarte des (și cum le eviți)
Câteva detalii mici fac diferența între un program corect și unul care „pare” corect. Ține minte cele două reguli de mai jos.
1) = NU este ==
❌ Greșit: if (ok = true) (aici faci atribuire!)
✅ Corect: if (ok == true) sau mai simplu: if (ok)
2) Negarea cu !
Dacă ai o funcție care întoarce true/false, negarea e foarte utilă:
// dacă NU e prim:
if (!estePrim(v[i])) {
// atunci proprietatea „toate sunt prime” pică
}
Când verifici „toate sunt pozitive”, condiția corectă pentru eșec este v[i] <= 0,
nu doar v[i] < 0 (0 nu este pozitiv).
Exercițiu de completare - Verificare elemente pare
Completează TOATE spațiile libere din codul C++ pentru verificarea dacă toate elementele sunt pare:
Bancă de cuvinte:
Click pe un spațiu liber, apoi pe un cuvânt din bancă.
Test de înțelegere: Care este strategia corectă?
Test rapid - alegerea flag-ului inițial:
Pentru fiecare situație, alege valoarea inițială corectă a flag-ului:
Verificare:
"Toate elementele sunt pozitive"
Verificare:
"Există cel puțin un element par"
Verificare:
"Niciun element nu este zero"
Verificarea proprietăților complexe: Număr prim & Număr perfect
1. Număr prim
Definiție: Un număr prim este un număr natural mai mare decât 1 care are exact doi divizori: 1 și el însuși.
bool estePrim(int x) { // Numerele mai mici decât 2 nu sunt prime if (x < 2) return false; // 2 este singurul număr prim par if (x == 2) return true; // Dacă e par și mai mare ca 2, nu e prim if (x % 2 == 0) return false; // Verificăm divizorii impari până la sqrt(x) for (int d = 3; d * d <= x; d += 2) { if (x % d == 0) { return false; // Am găsit un divizor, deci nu e prim } } return true; // Nu am găsit divizori, deci e prim } // Exemplu de utilizare în verificarea unui vector: bool toatePrime = true; for (int i = 0; i < n; i++) { if (!estePrim(v[i])) { // Dacă NU e prim toatePrime = false; break; } }
2. Număr perfect
Definiție: Un număr perfect este un număr natural egal cu suma divizorilor săi proprii
(toți divizorii mai mici decât numărul însuși, inclusiv 1).
Exemplu: 6 = 1 + 2 + 3 (6 este perfect)
// Funcție care verifică dacă un număr este perfect bool estePerfect(int x) { // Cel mai mic număr perfect este 6 if (x < 2) { return false; } // 1 este divizor pentru orice număr > 1 int sumaDivizori = 1; // Căutăm divizori începând de la 2 până la sqrt(x) for (int d = 2; d * d <= x; d++) { if (x % d == 0) { // Adăugăm divizorul d sumaDivizori += d; // Dacă d != x/d, adăugăm și celălalt divizor if (d != x / d) { sumaDivizori += x / d; } } } // Verificăm dacă suma divizorilor proprii este egală cu numărul return (sumaDivizori == x); } /* Exemplu de utilizare: Verificăm dacă există cel puțin un număr perfect în vector */ bool existaPerfect = false; for (int i = 0; i < n; i++) { if (estePerfect(v[i])) { existaPerfect = true; break; } }
Primele numere perfecte: 6, 28, 496, 8128, 33550336, ...
Observație: Toate numerele perfecte pare se termină în 6 sau 28.
Sfaturi practice pentru verificarea proprietăților
"Toate" → true
"Există" → false
"Niciun" → true
Odată ce știi răspunsul final, nu mai are rost să continui verificarea.
Scrie funcții separate pentru estePrim(), estePerfect(), estePalindrom() etc.
Vector gol, vector cu 1 element, toate elemente egale, valori extreme.
Încălzire (2 minute)
Test rapid - identificare strategie flag: Pentru fiecare verificare, spune dacă începi cu true sau false:
- Toate elementele sunt mai mari decât 10 → verifică
- Există cel puțin un element egal cu 0 → verifică
- Niciun element nu este mai mic decât -5 → verifică
📌 Regulă: "Toate" → true, "Există" → false, "Niciun" → true
PbInfo #402 - Toate elementele pozitive
Enunț:
Cerință: Se citește un număr n și apoi n numere întregi. Să se verifice dacă toate elementele sunt pozitive.
Date de intrare:
Programul citește de la tastatură numărul n, apoi n numere întregi.
Date de ieșire:
Programul va afișa pe ecran "DA" dacă toate elementele sunt pozitive, altfel va afișa "NU".
Exemplu:
Intrare:
5 10 20 5 30 15
Ieșire:
DA
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
bool toatePozitive = true;
for (int i = 0; i < n; i++) {
if (v[i] <= 0) {
toatePozitive = false;
break;
}
}
if (toatePozitive) {
cout << "DA" << endl;
} else {
cout << "NU" << endl;
}
return 0;
}
PbInfo #403 - Există cel puțin un număr par
Enunț:
Cerință: Se citește un număr n și apoi n numere întregi. Să se verifice dacă există cel puțin un număr par în șir.
Date de intrare:
Programul citește de la tastatură numărul n, apoi n numere întregi.
Date de ieșire:
Programul va afișa pe ecran "DA" dacă există cel puțin un număr par, altfel va afișa "NU".
Exemplu:
Intrare:
5 7 3 9 2 5
Ieșire:
DA
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
bool existaPar = false;
for (int i = 0; i < n; i++) {
if (v[i] % 2 == 0) {
existaPar = true;
break;
}
}
if (existaPar) {
cout << "DA" << endl;
} else {
cout << "NU" << endl;
}
return 0;
}
PbInfo #404 - Niciun element nu este zero
Enunț:
Cerință: Se citește un număr n și apoi n numere întregi. Să se verifice dacă niciun element nu este egal cu 0.
Date de intrare:
Programul citește de la tastatură numărul n, apoi n numere întregi.
Date de ieșire:
Programul va afișa pe ecran "DA" dacă niciun element nu este 0, altfel va afișa "NU".
Exemplu:
Intrare:
5 10 20 5 30 15
Ieșire:
DA
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
bool niciunZero = true;
for (int i = 0; i < n; i++) {
if (v[i] == 0) {
niciunZero = false;
break;
}
}
if (niciunZero) {
cout << "DA" << endl;
} else {
cout << "NU" << endl;
}
return 0;
}
Exercițiul Practic: Verificări complexe cu flag-uri
Sarcini de lucru
Completează următoarele sarcini pentru a-ți consolida cunoștințele despre verificarea proprietăților
Sarcina 1: Analiză și corectare cod
Analizează următorul cod și găsește greșelile:
#include <iostream>
using namespace std;
int main() {
int n = 5;
int vector[5] = {8, 3, 10, 2, 7};
// Verificare: toate elementele sunt mai mari decât 5?
bool toateMaiMari = false; // începem cu false
for (int i = 0; i < n; i++) {
if (vector[i] > 5) {
toateMaiMari = true;
}
}
if (toateMaiMari = true) {
cout << "Toate sunt mai mari decat 5" << endl;
} else {
cout << "Nu toate sunt mai mari decat 5" << endl;
}
return 0;
}
Soluție pentru Sarcina 1:
Greșeli identificate și corecții:
- 1. Valoare inițială greșită a flag-ului:
bool toateMaiMari = false;este greșit pentru verificarea "toate".
Corect:bool toateMaiMari = true; - 2. Logica inversă în buclă:
Când găsim un element care NU este mai mare decât 5, ar trebui să setăm flag-ul pe false.
Corect:if (vector[i] <= 5) toateMaiMari = false; - 3. Lipsă break pentru optimizare:
Odată ce am găsit un contraexemplu, nu mai are rost să continuăm.
Corect: Adăugămbreak;după setarea flag-ului pe false. - 4. Eroare de atribuire în loc de comparație:
if (toateMaiMari = true)este atribuire, nu comparație.
Corect:if (toateMaiMari == true)sau simpluif (toateMaiMari)
Sarcina 2: Implementare completă
Cerință: Scrie un program care citește n, apoi n numere. Programul verifică și afișează:
- Dacă toate elementele sunt pozitive
- Dacă există cel puțin un element par
- Dacă niciun element nu este mai mic decât -10
- Dacă toate elementele sunt mai mici decât 100
Soluție pentru Sarcina 2:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// 1. Toate elementele sunt pozitive?
bool toatePozitive = true;
for (int i = 0; i < n; i++) {
if (v[i] <= 0) {
toatePozitive = false;
break;
}
}
// 2. Există cel puțin un element par?
bool existaPar = false;
for (int i = 0; i < n; i++) {
if (v[i] % 2 == 0) {
existaPar = true;
break;
}
}
// 3. Niciun element nu este mai mic decât -10?
bool niciunMaiMicCaMinus10 = true;
for (int i = 0; i < n; i++) {
if (v[i] < -10) {
niciunMaiMicCaMinus10 = false;
break;
}
}
// 4. Toate elementele sunt mai mici decât 100?
bool toateMaiMiciCa100 = true;
for (int i = 0; i < n; i++) {
if (v[i] >= 100) {
toateMaiMiciCa100 = false;
break;
}
}
cout << "1. Toate elementele sunt pozitive: "
<< (toatePozitive ? "DA" : "NU") << endl;
cout << "2. Exista cel putin un element par: "
<< (existaPar ? "DA" : "NU") << endl;
cout << "3. Niciun element nu este mai mic decat -10: "
<< (niciunMaiMicCaMinus10 ? "DA" : "NU") << endl;
cout << "4. Toate elementele sunt mai mici decat 100: "
<< (toateMaiMiciCa100 ? "DA" : "NU") << endl;
return 0;
}