🗂️ Structuri (struct)

Capitolul 10 — Tipuri compuse de date: declarare, câmpuri, vectori, sortare, BAC

structdate compusesortareBACtipuri utilizator
📖 12 min
0
🗂️

Declarare struct

💡 Ce este un struct?

Un struct este un tip de dată definit de programator care grupează mai multe câmpuri de tipuri diferite sub un singur nume. Este util când vrem să reprezentăm o entitate (persoană, produs, student) cu mai multe atribute.

// Sintaxa generală
struct NumeTip {
    tip1 camp1;
    tip2 camp2;
    // ...
};  // <-- punct-virgulă obligatoriu!

// Exemplu: struct pentru un student
struct Student {
    char nume[50];
    int varsta;
    float medie;
};

// Declarare variabile de tip Student
Student s1, s2;
Student clasa[30];  // tablou de 30 de studenți
Atenție: Definiția struct-ului se pune global (înainte de orice funcție), nu înăuntrul lui main(). Altfel nu este vizibil în alte funcții.
Struct tipice la BAC:
  • Persoana: nume + vârstă + salariu
  • Student: nume + medie + grup
  • Produs: cod + denumire + preț + stoc
  • Punct: x + y (coordonate 2D)
🔍

Câmpuri și acces

Câmpurile se accesează cu operatorul punct . (pentru variabile obișnuite) sau cu operatorul săgeată -> (pentru pointeri la struct).

struct Produs {
    char denumire[50];
    float pret;
    int stoc;
};

Produs p;

// Citire câmpuri
cin >> p.denumire >> p.pret >> p.stoc;

// Afișare câmpuri
cout << p.denumire << " " << p.pret << " " << p.stoc << endl;

// Modificare câmp
p.stoc -= 1;  // vânzare 1 produs
p.pret *= 1.1;  // scumpire 10%

// Atribuire struct (copie completă a tuturor câmpurilor)
Produs p2 = p;  // p2 este o copie independentă a lui p
Operator punct .

Folosit cu variabile struct obișnuite: p.pret, s.medie

Operator săgeată ->

Folosit cu pointeri la struct: ptr->pret echivalent cu (*ptr).pret

📋

Vector de structuri

Cel mai frecvent mod de utilizare la BAC: un tablou de struct-uri citit din tastatură sau fișier.

struct Elev {
    char nume[30];
    float medie;
    int clasa;
};

Elev v[100];
int n;

int main() {
    cin >> n;
    // Citire vector de struct-uri
    for (int i = 0; i < n; i++)
        cin >> v[i].nume >> v[i].medie >> v[i].clasa;

    // Afișare
    for (int i = 0; i < n; i++)
        cout << v[i].nume << "\t" << v[i].medie << "\t" << v[i].clasa << "\n";

    // Găsire elev cu media maximă
    int idxMax = 0;
    for (int i = 1; i < n; i++)
        if (v[i].medie > v[idxMax].medie)
            idxMax = i;
    cout << "Cel mai bun elev: " << v[idxMax].nume << endl;
}
Parcurgerea unui vector de struct-uri se face exact ca la un vector obișnuit — cu for (int i = 0; i < n; i++), accesând câmpurile cu v[i].câmp.
🔀

Sortare după câmp

Metoda 1: Bubble sort (clasic, O(n²))

// Sortare crescătoare după medie (Bubble Sort)
for (int i = 0; i < n-1; i++)
    for (int j = 0; j < n-i-1; j++)
        if (v[j].medie > v[j+1].medie) {
            Elev tmp = v[j];
            v[j] = v[j+1];   // interschimb complet (toate câmpurile)
            v[j+1] = tmp;
        }

Metoda 2: sort() cu comparator lambda (O(n log n))

// Necesită #include <algorithm>

// Sortare crescătoare după medie
sort(v, v+n, [](const Elev& a, const Elev& b) {
    return a.medie < b.medie;
});

// Sortare descrescătoare după medie
sort(v, v+n, [](const Elev& a, const Elev& b) {
    return a.medie > b.medie;
});

// Sortare alfabetică după nume
sort(v, v+n, [](const Elev& a, const Elev& b) {
    return strcmp(a.nume, b.nume) < 0;
});
La BAC apare frecvent: „sortează elevii descrescător după medie; la egalitate, crescător după nume"
// Sortare cu criteriu dublu
sort(v, v+n, [](const Elev& a, const Elev& b) {
    if (a.medie != b.medie) return a.medie > b.medie;  // descrescător medie
    return strcmp(a.nume, b.nume) < 0;               // crescător alfab.
});
⚙️

Structuri în funcții

struct Punct {
    double x, y;
};

// Transmitere prin valoare (funcția primește o COPIE)
double distanta(Punct a, Punct b) {
    double dx = a.x - b.x, dy = a.y - b.y;
    return sqrt(dx*dx + dy*dy);  // #include <cmath>
}

// Transmitere prin referință (funcția modifică originalul)
void translateaza(Punct& p, double dx, double dy) {
    p.x += dx;  // modifică originalul!
    p.y += dy;
}

// Funcție care returnează un struct
Punct mijloc(Punct a, Punct b) {
    Punct m;
    m.x = (a.x + b.x) / 2;
    m.y = (a.y + b.y) / 2;
    return m;
}

int main() {
    Punct p1 = {0, 0}, p2 = {3, 4};  // inițializare cu liste
    cout << distanta(p1, p2) << endl;     // 5.0
    translateaza(p1, 1, 1);              // p1 devine (1,1)
    Punct m = mijloc(p1, p2);            // m = (2, 2.5)
}
Prin valoare

Funcția primește copie. Modificările nu afectează originalul. Potrivit pentru funcții care doar citesc.

Prin referință (&)

Funcția modifică originalul. Potrivit pentru funcții de citire, sortare, modificare.

🎮

Demo interactiv — Struct în acțiune

Vizualizează cum arată un struct în memorie — fiecare câmp cu numele, tipul și valoarea lui. Sortează după orice câmp!

Normal
📦 Definiție: struct Student
📊 Statistici
Studenți: 0
Dimensiune struct: —
Apasă „Sortează după..."
📋 Vectorul de studenți
Apasă „Generează" pentru a crea studenți

5 probleme clasice cu structuri — elev, punct, carte, produs.

1 Elevul cu media maximă Ușor
Citește n elevi (nume + medie). Afișează numele elevului cu media cea mai mare.
Intrare:
3
Ana 9.20
Bogdan 8.50
Carmen 9.75
Ieșire:
Carmen
💡 Vezi soluția
struct Elev { string nume; double medie; };
int n; cin >> n;
Elev e[105], best;
best.medie = -1;
for (int i = 0; i < n; i++) {
    cin >> e[i].nume >> e[i].medie;
    if (e[i].medie > best.medie) best = e[i];
}
cout << best.nume;
2 Distanța între două puncte Ușor
Definește un struct Punct { double x, y; }. Citește două puncte și afișează distanța euclidiană (2 zecimale).
Intrare:
0 0
3 4
Ieșire:
5.00
💡 Vezi soluția
struct Punct { double x, y; };
Punct a, b;
cin >> a.x >> a.y >> b.x >> b.y;
double d = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
cout << fixed << setprecision(2) << d;
3 Sortare cărți după an Mediu
Citește n cărți (titlu, autor, an). Sortează crescător după an și afișează titlurile.
Intrare:
3
Baltagul Sadoveanu 1930
Maitreyi Eliade 1933
Ion Rebreanu 1920
Ieșire:
Ion
Baltagul
Maitreyi
💡 Vezi soluția
struct Carte { string titlu, autor; int an; };
Carte c[105];
int n; cin >> n;
for (int i = 0; i < n; i++) cin >> c[i].titlu >> c[i].autor >> c[i].an;
sort(c, c+n, [](Carte a, Carte b){ return a.an < b.an; });
for (int i = 0; i < n; i++) cout << c[i].titlu << '\n';

Idee: sort cu comparator lambda. La BAC poate apărea și ca bool cmp(Carte a, Carte b) { return a.an < b.an; }.

4 Produs cu reducere (funcție pe struct) Mediu
Definește Produs { string nume; double pret; int procReducere; }. Scrie funcția double pretFinal(Produs p). Afișează prețul final pentru fiecare din n produse citite.
Intrare:
2
Tricou 100 20
Pantaloni 200 10
Ieșire:
Tricou 80.00
Pantaloni 180.00
💡 Vezi soluția
struct Produs { string nume; double pret; int procReducere; };
double pretFinal(Produs p) {
    return p.pret * (100 - p.procReducere) / 100.0;
}
int n; cin >> n;
for (int i = 0; i < n; i++) {
    Produs p; cin >> p.nume >> p.pret >> p.procReducere;
    cout << p.nume << ' ' << fixed << setprecision(2) << pretFinal(p) << '\n';
}
5 Top 3 elevi (sortare descrescătoare) Dificil
Citește n elevi (nume + medie). Afișează primii 3 elevi în ordine descrescătoare a mediei. Dacă n < 3, afișează toți elevii.
Intrare:
5
Ana 9.2
Bogdan 8.5
Carmen 9.75
Dan 7.8
Eva 9.5
Ieșire:
Carmen 9.75
Eva 9.50
Ana 9.20
💡 Vezi soluția
struct Elev { string nume; double medie; };
int n; cin >> n;
Elev e[105];
for (int i = 0; i < n; i++) cin >> e[i].nume >> e[i].medie;
sort(e, e+n, [](Elev a, Elev b){ return a.medie > b.medie; });
int k = min(3, n);
for (int i = 0; i < k; i++)
    cout << e[i].nume << ' ' << fixed << setprecision(2) << e[i].medie << '\n';

Trucuri: 1) return a.medie > b.medie pentru descrescător; 2) min(3, n) evită out-of-bounds dacă sunt mai puțini elevi.

💡 Recomandare BAC: definește struct-ul în afara funcțiilor (la nivel global) ca să fie vizibil peste tot.
🎓

Probleme tip BAC — struct

Problema 1: Elevii cu media peste 9

struct Elev { char nume[30]; float medie; };
Elev v[100]; int n;

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) cin >> v[i].nume >> v[i].medie;

    // a) Afișare elevi cu medie > 9
    for (int i = 0; i < n; i++)
        if (v[i].medie > 9) cout << v[i].nume << endl;

    // b) Sortare descrescătoare după medie
    sort(v, v+n, [](const Elev& a, const Elev& b) {
        return a.medie > b.medie;
    });

    // c) Afișare clasament
    for (int i = 0; i < n; i++)
        cout << i+1 << ". " << v[i].nume << " - " << v[i].medie << "\n";
}

Problema 2: Inventar produse — prețul mediu și produsele sub medie

struct Produs { char cod[10]; float pret; int stoc; };
Produs p[500]; int n;

int main() {
    cin >> n;
    float suma = 0;
    for (int i = 0; i < n; i++) {
        cin >> p[i].cod >> p[i].pret >> p[i].stoc;
        suma += p[i].pret;
    }
    float mediu = suma / n;
    cout << "Pret mediu: " << mediu << endl;

    // Produse sub prețul mediu
    cout << "Sub medie:" << endl;
    for (int i = 0; i < n; i++)
        if (p[i].pret < mediu)
            cout << p[i].cod << ": " << p[i].pret << endl;
}
Pași problemă struct la BAC

1. Declară struct global
2. Citește tablou de struct
3. Parcurge și filtrează
4. Sortează dacă e cerut
5. Afișează rezultate

Greșeli frecvente

- Struct definit în main (nu e global)
- Uitat ; după } struct
- Sortat după câmpul greșit
- Compararea float cu ==