Struct în C++: câmpuri și tablouri de structuri
O structură C++ grupează date care descriu același obiect. Cu `struct Elev { int cod; double nota; };`, fiecare elev are propriul cod și propria notă. Accesul se face prin punct: `e.cod` și `e.nota`.
În acest material
O structură C++ grupează date care descriu același obiect. Cu struct Elev { int cod; double nota; };, fiecare elev are propriul cod și propria notă. Accesul se face prin punct: e.cod și e.nota.
Structurile evită sincronizarea fragilă a mai multor tablouri paralele. Dacă sortezi separat codurile și notele, poți asocia accidental nota unui elev cu alt cod. Mutarea unei structuri păstrează împreună câmpurile obiectului.
Cum funcționează
Definiția tipului descrie câmpurile, dar nu creează automat un elev. Declarația Elev e{}; creează un obiect inițializat. Într-un tablou Elev a[100], expresia a[i].nota selectează întâi elevul de la indicele i și apoi câmpul nota. Forma a.nota[i] nu descrie aceeași structură și nu este validă pentru această declarație.
O atribuire între două obiecte de același tip copiază câmpurile lor. Pentru structuri care conțin tablouri clasice, atribuirea structurii copiază și acele elemente, spre deosebire de atribuirea directă între două tablouri independente. Dacă structura conține pointeri, se copiază adresele, nu obiectele către care indică: aceasta este o diferență importantă pentru proprietatea memoriei.
Programul citește între unu și o sută de elevi, cu coduri întregi distincte și note valide. Alege nota maximă, iar la egalitate codul mai mic. Avem nevoie de o regulă explicită de departajare, pentru că ordinea citirii nu ar trebui să schimbe răspunsul dacă enunțul cere codul minim.
Exemplu urmărit pas cu pas
Pentru elevii (17,8.5), (4,9), (12,9), candidatul inițial este 17. Elevul 4 are nota mai mare și îl înlocuiește. Elevul 12 are aceeași notă, dar codul mai mare, deci candidatul rămâne 4.
O comparație a codurilor înaintea notelor ar rezolva altă problemă. Condiția trebuie citită ca două situații: o notă strict mai bună sau aceeași notă și un cod mai mic. Parantezele fac vizibilă această intenție.
Implementare C++17
Varianta cu tablou clasic:
#include <iostream>
struct Elev {
int cod;
double nota;
};
int main() {
int n;
std::cin >> n;
Elev a[100];
for (int i = 0; i < n; ++i)
std::cin >> a[i].cod >> a[i].nota;
int p = 0;
for (int i = 1; i < n; ++i)
if (a[i].nota > a[p].nota || (a[i].nota == a[p].nota && a[i].cod < a[p].cod))
p = i;
std::cout << a[p].cod << '\n';
}
Varianta echivalentă cu std::vector folosește aceleași limite și aceiași indici:
#include <iostream>
#include <vector>
struct Elev {
int cod;
double nota;
};
int main() {
int n;
std::cin >> n;
std::vector<Elev> a(n);
for (int i = 0; i < n; ++i)
std::cin >> a[i].cod >> a[i].nota;
int p = 0;
for (int i = 1; i < n; ++i)
if (a[i].nota > a[p].nota || (a[i].nota == a[p].nota && a[i].cod < a[p].cod))
p = i;
std::cout << a[p].cod << '\n';
}
De ce funcționează și cât costă
După prelucrarea primilor k elevi, indicele p identifică cel mai bun elev din acel prefix conform ordinii stabilite. Următorul elev îl înlocuiește exact dacă este mai bun. La final, prefixul este întregul tablou.
Timpul este O(n), memoria pentru stocare O(n), iar alegerea candidatului folosește O(1) memorie suplimentară. Dacă nu ai nevoie ulterior de toate datele, poți păstra numai elevul curent și candidatul, reducând stocarea la O(1).
Greșeli frecvente
Nu confunda numele tipului cu numele obiectului. Nu omite punctul și virgula de după definiția structurii. Pentru numere reale rezultate din calcule, egalitatea exactă poate fi nepotrivită; aici comparăm note citite în aceeași reprezentare, fără calcule intermediare.
Exersează
Modifică regula pentru a alege nota minimă și, la egalitate, codul maxim. Ce operatori se schimbă?
Rezolvare explicată: Comparația notelor devine strict mai mic, iar comparația codurilor strict mai mare. Egalitatea notelor și legătura logică dintre cele două cazuri rămân neschimbate.
Continuă să înveți
Întrebări frecvente
Ce diferență este între struct și un tablou?
Structura poate grupa câmpuri de tipuri diferite, identificate prin nume. Un tablou conține elemente de același tip, identificate prin indici. Le poți combina într-un tablou de structuri.
Cum accesez nota celui de-al doilea elev?
Dacă indicii încep de la zero, folosești a[1].nota. Selectezi mai întâi elementul tabloului și apoi câmpul obiectului respectiv.
Se copiază întreaga structură la atribuire?
Pentru o structură simplă, atribuirea copiază câmpurile. Dacă unele câmpuri sunt pointeri, se copiază adresele, nu automat și memoria indicată de acestea.
Pot transmite o structură unei funcții?
Da. Prin valoare obții o copie; prin referință poți modifica originalul. O referință constantă permite citirea fără copiere și fără modificarea obiectului.
De ce folosim o regulă de departajare?
Mai multe obiecte pot avea aceeași valoare principală. Regula secundară stabilește un rezultat determinist și trebuie să corespundă exact cerinței din enunț.
Un pas mai departe
Se încarcă progresul…