Tipuri de date neomogene (struct)
Până acum am folosit tipuri simple: int,
double, char, bool. Toate
stochează o singură valoare.
Dar când descriem un elev, nu avem o singură valoare - avem nume, vârstă, note. Când descriem un punct în plan, avem x și y.
Pentru a grupa mai multe valori într-un singur “tip”, folosim
struct - un tip de date
neomogen (conține valori de tipuri
diferite).
Declararea unui struct
struct Elev {
char nume[50];
int varsta;
double medie;
};Am creat un tip nou numit Elev.
Fiecare Elev are trei câmpuri (sau
membri): nume, varsta,
medie.
Atenție: ; după acoladele
struct-ului este obligatoriu! E una dintre cele
mai frecvente greșeli.
Folosirea unui struct
Elev e;
strcpy(e.nume, "Ana");
e.varsta = 15;
e.medie = 9.75;
cout << e.nume << " " << e.varsta << " " << e.medie;
// Ana 15 9.75Accesăm câmpurile cu . (punct):
variabila.camp.
Inițializare directă
Elev e = {"Ana", 15, 9.75}; // în ordinea câmpurilorValorile se atribuie în ordinea declarării câmpurilor.
Vector de struct-uri
Cea mai utilă aplicație - un vector de elevi:
Elev elevi[101];
int n = 3;
strcpy(elevi[1].nume, "Ana");
elevi[1].varsta = 15;
elevi[1].medie = 9.75;
strcpy(elevi[2].nume, "Mihai");
elevi[2].varsta = 16;
elevi[2].medie = 8.50;
strcpy(elevi[3].nume, "Elena");
elevi[3].varsta = 14;
elevi[3].medie = 9.90;Citire dintr-un fișier
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
struct Elev {
char nume[50];
int varsta;
double medie;
};
Elev elevi[101];
int n;
int main()
{
fin >> n;
for (int i = 1; i <= n; i++) {
fin >> elevi[i].nume >> elevi[i].varsta >> elevi[i].medie;
}
for (int i = 1; i <= n; i++) {
fout << elevi[i].nume << " | "
<< elevi[i].varsta << " ani | "
<< "media " << elevi[i].medie << "\n";
}
return 0;
}date.in:
3
Ana 15 9.75
Mihai 16 8.50
Elena 14 9.90date.out:
Ana | 15 ani | media 9.75
Mihai | 16 ani | media 8.5
Elena | 14 ani | media 9.9Exemplu: elevul cu media maximă
Elev maxElev = elevi[1];
for (int i = 2; i <= n; i++) {
if (elevi[i].medie > maxElev.medie)
maxElev = elevi[i]; // copiere întregului struct
}
fout << "Cel mai bun: " << maxElev.nume << " cu media " << maxElev.medie;Atribuirea între struct-uri copiază toate câmpurile automat.
Exemplu: punct în plan
struct Punct {
int x, y;
};
Punct a, b;
a.x = 3; a.y = 4;
b.x = 6; b.y = 8;
// Distanța (la pătrat)
int dx = a.x - b.x;
int dy = a.y - b.y;
int distPatrat = dx * dx + dy * dy;
cout << distPatrat; // 25Struct cu câmpuri de tipuri mixte
struct Carte {
char titlu[100];
char autor[50];
int an;
double pret;
bool inStoc;
};
Carte c = {"Hobbitul", "Tolkien", 1937, 45.99, true};Struct-ul poate conține orice tipuri: numere, șiruri,
bool, chiar alte struct-uri.
Struct în struct
struct Data {
int zi, luna, an;
};
struct Elev {
char nume[50];
Data dataNasterii;
double medie;
};
Elev e;
strcpy(e.nume, "Ana");
e.dataNasterii.zi = 15;
e.dataNasterii.luna = 3;
e.dataNasterii.an = 2010;
e.medie = 9.75;Accesăm câmpul interior cu punct dublu:
e.dataNasterii.zi.
Struct și funcții
void afiseaza(Elev e) {
cout << e.nume << " " << e.varsta << " " << e.medie << endl;
}
bool esteBun(Elev e) {
return e.medie >= 9.0;
}
int main()
{
Elev ana = {"Ana", 15, 9.75};
afiseaza(ana);
if (esteBun(ana))
cout << "Ana are media mare!";
return 0;
}Transmitere prin referință
Pentru a modifica un struct într-o funcție, folosim
&:
void creste(Elev &e) {
e.varsta++;
}
Elev ana = {"Ana", 15, 9.75};
creste(ana);
cout << ana.varsta; // 16Performanță: struct-urile mari se transmit
mai eficient prin referință
(Elev &e) chiar dacă nu le modificăm - evităm
copierea.
Sortare vector de struct-uri
#include <algorithm>
bool cmp(Elev a, Elev b) {
return a.medie > b.medie; // descrescător după medie
}
sort(elevi + 1, elevi + n + 1, cmp);Definim o funcție de comparare care primește două struct-uri
și returnează true dacă primul trebuie să fie
înainte.
Sortare după mai multe criterii
bool cmp(Elev a, Elev b) {
if (a.medie != b.medie)
return a.medie > b.medie; // întâi după medie descrescător
return strcmp(a.nume, b.nume) < 0; // apoi alfabetic
}Greșeli frecvente
1. Lipsa ; după
struct
struct Elev {
int varsta;
} // LIPSEȘTE ; - eroare de compilare!Corect:
struct Elev {
int varsta;
};2. Accesare fără punct
Elev e;
varsta = 15; // GREȘIT - ce e "varsta"? o variabilă globală?
e.varsta = 15; // CORECT3. Comparare struct-uri cu
==
Elev a, b;
if (a == b) // EROARE de compilareC++ nu știe cum să compare două struct-uri. Trebuie să compari câmp cu câmp:
if (a.varsta == b.varsta && a.medie == b.medie && strcmp(a.nume, b.nume) == 0)4. Citire/afișare direct
Elev e;
cin >> e; // GREȘIT
cout << e; // GREȘITTrebuie pe câmpuri:
cin >> e.nume >> e.varsta >> e.medie;
cout << e.nume << " " << e.varsta;Ce să reții
structgrupează mai multe valori (posibil de tipuri diferite) într-un tip nou.- Declarare:
struct Nume { tip1 camp1; tip2 camp2; };(atenție la;). - Acces la câmp:
variabila.camp. - Inițializare:
Elev e = {"Ana", 15, 9.75};. - Copiere automată cu
=între struct-uri. - Poate fi transmis la funcții (prin valoare sau referință).
- Sortabil cu
sortși un comparator custom. - Nu suportă direct
cin,cout,==- trebuie pe câmpuri.