Sunteți pe pagina 1din 25

C11:Tipuri structurate de date

C11: Tipuri structurate de date

▪ Tablouri

▪ Structuri
___________________

▪ Campuri de biti

▪ Uniuni

▪ Enumerari

▪ Tipuri definite de utilizator (typedef)


C11: Tipuri structurate de date

Limbajul C/C++ permite creare tipurilor de date (definite de utilizator) in


urmatoarele moduri:

▪ Structura (struct) – entitate ce grupeaza mai multe campuri de tipuri C10


diferite sub acelasi nume

▪ Camp de biti - variatiune a structurii cu acces usor la bitii individuali

▪ Uniune (union) –aceleasi zona de memorie poate sa fie folosita


alternativ/dupa caz de doua sau mai multe tipuri diferite de variabile

▪ Enumerare (enum) – lista de constante intregi cu nume

▪ Tipuri definite de utilizator (typedef) – se da un nume nou unui tip


existent
Campuri de biti
Camp de biti = tip special de camp al unei structuri care are precizata lungimea
in biti.

E permis accesul la mai putini biti decat are tipul de date => putem stoca mai
comprimat campurile unei structuri (dar mereu pe minim n octeti).

Sintaxa:
struct nume_tip_complex_date {
tip_camp_1 nume_camp_1:lungime_1;
tip_camp_2 nume_camp_2:lungime_2;
---------------------------------
tip_camp_n nume_camp_n:lungime_n;
} lista_variabile_de acest_tip;

OBS: lungime_x poate sa lipseasca, daca nu se poate face/doreste stocare comprimata.


Campuri de biti

struct nume_tip_complex_date {
tip_camp_1 nume_camp_1:lungime_1;
tip_camp_2 nume_camp_2:lungime_2;
---------------------------------
tip_camp_n nume_camp_n:lungime_n;
} lista_variabile_de acest_tip;

Observatii:
- tipul campului de biti poate fi doar: int, long int, short int , unsigned sau
signed.
- lungime_x → numarul de biti dintr-un camp.
- campul de biti cu lungimea =1 → unsigned (un singur bit nu poate avea semn)
- unele compilatoare permit campuri de biti→ doar unsigned.
Campuri de biti
Exemplu: O carte de joc poate sa fie caracterizata ca tip complex de date prin
valoare (2-14) si culoare (exista 4 culori)
struct CarteJoc {
unsigned short int valoare; //2 octeti = 2*8 biti
unsigned short int culoare; // 2 octeti = 2*8 biti
};

struct CarteJoc Pachet [52];


cout<<sizeof(CarteJoc); //4
cout<<sizeof(Pachet); //208

Ocupam spatiu in plus? Da!


OBS Pe un bit se pot reprezenta 2 valori(0 sau 1), pe x biti putem reprezenta
2^x valori
Trebuie sa gasim puterea lui 2 imediat mai mare sau egala cu valoarea maxima
de reprezentat. Puterea reprezinta numarul de biti necesari reprezentarii.
ex: 2^2= 4 – pot sa reprezint maxim 4 valori pe 2 biti; 2^5=32 pot sa reprezint
max 32 valori folosind 5 biti
16=2^4 (si implicit si 14) valori se pot reprezenta pe 4 biti
4=2^2 valori se pot reprezenta pe 2 biti
Campuri de biti

struct CarteJoc {
unsigned short int valoare : 4; // 4 biti
unsigned short int culoare : 2; // 2 biti
};

struct CarteJoc Pachet[52];

cout<<sizeof(CarteJoc); //2 octeti


cout<<sizeof(Pachet); //104 octeti

=>salvez spatiu

OBS: Chiar daca reprezentarea e pe 6 biti, se rotunjeste la un octet /camp


=> 2 octeti !
Campuri de biti
In aceeasi structura putem avea campuri de biti si campuri “normale”:
struct Adresa {
char *str;
int nr;
char cod[7];
};

struct Angajat {
/*struct*/ Adresa adr;
float salariu;
unsigned short int ore_zi: 1; // part time sau full time
unsigned short int impozit: 7; // procent x% din salariu (0-100)
};

//in loc de 2x 2 = 4 octeti pentru cele 2 campuri short int = > ocupam doar 2 octeti
//Pot sa mai reduc dimensiunea?
Campuri de biti

Cum puteti reprezenta cat mai comprimat tipul de date piesa puzzle daca o piesa
are urmatoarele caracteristici:
- tip intre 0 si 2 : colt, muchie, interior;
- material: carton sau plastic
- id: intre 0 si nr_max piese care este 56

struct Piesa {
unsigned short int tip: 2;
unsigned short int material: 1;
unsigned short int id: 6;
};

//in loc de 3x 2 = 6 octeti pentru cele 3 capuri int = > ocupam doar 3 octeti
Campuri de biti
struct Piesa {
unsigned int tip: 2;
unsigned int material: 1;
unsigned int id: 6;
};
Valorile mai mari
decat domeniul
//main campului de biti sunt
reprezentate cu
Piesa p;
pierdere de informatie
p.material = 5; (restul impartirii la
1
cout<<p.material<<endl; 2^x) si conversie la
tipul precizat.

p.material = 7;
cout<<p.material<<endl; 1

p.material = 6;
cout<<p.material<<endl; 0
Uniuni
- tip special de structura ai carei membri/campuri folosesc, la momente
diferite de timp, aceeasi locatie in memorie.
- ocupa spatiu cat cel mai mare camp: max(sizeof(tip_camp_i)).
- campurile unei uniuni au, de obicei, tipuri diferite

Sintaxa:

union nume_uniune{
tip_camp_1 nume_camp_1;
tip_camp_2 nume_camp_2 ;
---------------------------------
tip_camp_n nume_camp_n:
} lista_variabile_tip_union;
Uniuni
raspuns_numeric
union raspuns_grila{
int raspuns_numeric; Octet 1 Octet 2 Octet 3 Octet 4
char raspuns_caracter;
};
raspuns_caracter
In C++ union poate sa lipseasca
union raspuns_grila r1,r2; din fata numelui uniunii atunci
r1.raspuns_numeric=4; cand ma refer la un tip de date
r2.raspuns_caracter=‘a’;
cout<<r1.raspuns_numeric << “ si “<< r2.raspuns_caracter<<endl; //4 si a

r1.raspuns_caracter=‘b’;
//la aceasta atribuire am pierdut informatia -4 – stocata in raspuns numeric
cout<<r1.raspuns_caracter; //b
cout<<r1.raspuns_numeric;// o valoare fara insemnatate, 4 a fost pierdut

O variabila de tip union ocupa memorie suficienta pentru a stoca cel mai mare
camp (in cazul de mai sus max(sizeof(char), sizeof(int)) ).
Uniuni
nume
union Tara{
char *nume; Octet 1 Octet 2 Octet 3 Octet 4
char cod[3];
};
cod
//main
Tara t;
t.nume=(char*)malloc(sizeof(char)*(strlen(“O tara”)+1));
strcpy(t.nume, “O tara”);
cout<<t.nume<<endl; Implementati o functie
//Cum se incarca memoria? care initializeaza valoarea
stocata intr-o variabila de
strcpy(t.cod,”OT”); tip tara cu date citite de
//Dar acum? Cum arata memoria? la tastatura.
//Avem vreo problema?
//Da - “memory leak”

free(t.nume); //inainte sa folosesc alt camp din uniune


#include <iostream>
#include <string.h> Uniuni
#include <stdlib.h>
using namespace std;

union Tara{ char* nume;


char cod[3]; };

void init(Tara &t){ //in C – union Tara &t


char c, sir[100];
cout<<"vreti sa stocati numele sau codul? n / a "<<endl;
cin>>c;
cout<<"care e numele sau codul? "<<endl;
cin >>sir;
switch (c){
case 'a':{ strcpy(t.cod,sir);
break;}
case 'n':{ t.nume = (char*)malloc(sizeof(char)*(strlen(sir)+1));
strcpy(t.nume,sir); int main (){
break;} Tara x;
default: { cout<<"nume NULL"; init(x);
t.nume=NULL; }
break;} //Ce problema am?
} //Cum afisez?
} //Ce pot face? Tema
Enumerari

➢ o enumerare e o multime de constante de tip intreg care specifica toate


valorile permise pe care le poate avea o variabila de acel tip

➢ atat numele enumerarii cat si lista de variabile sunt optionale – dar nu simultan

➢ constanta intreaga asociata unui element al enumerarii e fie implicit, fie explicit
specificata

➢ implicit – primului element i se asociaza valoarea 0; iar pentru restul


elementelor - valoarea elementului precedent incrementata cu 1.

Sintaxa:

enum nume_tip {
lista constante (enumerare)
} lista variabile;
Enumerari

enum E{x, y, z}; → x = 0, y = 1, z = 2

enum X {a, b, c=10, d}; → a = 0, b = 1, c = 10, d = 11

enum {a=4, b=6 , c=-1, d = -4} ex; → a = 4, b = 6, c = -1, d = - 4

enum boolean {fals, adevarat}; → fals=0, adevarat=1

enum zile_sapt{
luni=1,marti,miercuri,joi,vineri,sambata,duminica
}azi, maine;

azi = joi; //o variabila de tip enumerare poate lua orice valoare enumerata.
cout<<azi<<endl; //4

maine=(zile_sapt)(azi+1); // maine=(zile_sapt)5;
cout<<maine<<endl; //5
cout<<duminica<<endl;//7
//fiind de tip int se pot folosi ca indici in tablouri
#include <iostream> int main(){
enum stare starea_vremii;
using namespace std;
//Presupunem ca lucram la Agentia Nationala de Meteorologie starea_vremii = canicula;
//Urmatoarele stari pot descrie diferite conditii atmosferice posibile. avertizari(starea_vremii);

enum stare{ soare, ploaie, ninsoare, ceata, canicula}; starea_vremii = (stare)1;


avertizari(starea_vremii);
void avertizari(enum stare starea_vremii){ return 0;
switch(starea_vremii) { }
case soare: cout<<"Va fi soare! Pregatiti crema de plaja!"<<endl;
break;
case ploaie: cout<<"Va ploua! Nu uitati umbrela!"<<endl;
break;
case ninsoare: cout<<"Va ninge! Pregatiti saniile si schiurile!"<<endl;
break;
case ceata: cout<<"Va fi ceata! Ce misterios va fi afara!"<<endl;
break;
case canicula: cout<<"Va fi canicula! Ce buna va fi o inghetata!"<<endl;
break;
}
}
Specificatorul typedef

• defineste explicit tipuri noi de date folosindu-se de unele vechi.


• se asociaza un nume (sinonim) unui tip de date.

Sintaxa:
typedef <definitie_tip> <nume_nou>;

Exemple:
typedef unsigned int nr_natural;
nr_natural m,n,i;

typedef struct {
double re, im;
} nr_complex; //special utila in C ca sa nu ma refer la structura prin struct complex

nr_complex nr;
nr.re=nr.im=1;
cout<<nr.re<<“ "<<nr.im;
C10: Tipuri structurate de date

Definiti tipul de date student. Un student are nume, CNP, grupa, note luate la
materiile de pe semestrul 1: Analiza, Algebra, Fizica, Programare, Engleza.

Creati un vector de studenti (seria voastra).

Implementati o functie care citeste date de la tastatura pentru un student.


Implementati o functie care afiseaza datele unui student.
Implementati o functie care permite setarea notei la o materie pentru un student.
Implementati o functie care calculeaza media unui student.

Afisati toti studentii cu bursa (media >8.5) din grupa 1311.


Afisati toti studentii cu nota de 9 sau 10 la Algebra.
#include <iostream>
#include <string.h>

using namespace std;

enum Materie { Analiza, Algebra, Fizica, Programare, Engleza };

enum Grupa { Gr_1311 =1 , Gr_1312, Gr_1313 , Gr_1314};

struct Student{
char *nume;
char CNP[14];
Grupa gr;
int note[5]; // putem folosi indici de tip Materie
};
void citesc(Student &s){
cout<<"Dati numele: "<<endl;
char aux[100];
cin>>aux;

int l = strlen(aux);
s.nume = (char*)malloc(sizeof(char) * (l+1));
strcpy( s.nume, aux);

cout<<"Dati CNP-ul: "<<endl;


cin>> s.CNP;

int g;
cout<<"Dati grupa (intre 1 si 4): "<<endl; cin>>g;
s.gr = (Grupa) g;

cout<<"Dati notele pt Analiza, Algebra, Fizica, Programare, Engleza: "<<endl;


for (int i=Analiza; i<Engleza; i++ ) cin>>s.note[i];
}
//Implementati o functie care permite setarea notei la o materie pentru un student.
void setNotaLaMateria(Student &s, Materie x, int nota){
s.note[x]=nota;
}
//Implementati o functie care afiseaza datele unui student.
void afisez(Student &s){
cout<<"Numele: "<<s.nume<<endl;
cout<<"CNP-ul: "<<s.CNP<<endl;
cout<<"Grupa: "<<s.gr<<endl;
cout<<"Notele la Analiza, Algebra, Fizica, Programare, Engleza sunt: ";
for (int i=Analiza; i<Engleza; i++ ) cout<<s.note[i]<<" ";
cout<<endl;
}
//Implementati o functie care calculeaza media unui student.
double getMedia(Student &s){
int media =0;
for (int i=Analiza; i<Engleza; i++ ) media+=s.note[i];
return (double)media/5;
int main(){
int n; cin>>n;
Student *vec=(Student*)malloc(sizeof(Student)*n);
for (int i=0; i<n; i++) citesc(vec[i]);

cout<<"schimba nota studentului cu pozitia 0, la Programare in 10"<<endl;


setNotaLaMateria(vec[0], Programare, 10);
//Afisati toti studentii cu bursa (media >8.5) din grupa 1311.
//ar trebui sa testez ca nu au restanta. Cum as face asta? Tema.
for (int i=0; i<n; i++)
if (getMedia(vec[i]) >= 8.5 && vec[i].gr == Gr_1311) afisez(vec[i]);
cout<<"_______________________________"<<endl;

//Afisati toti studentii cu 9 sau 10 la Algebra


for (int i=0; i<n; i++)
if ( vec[i].note[Algebra] > 8 ) afisez(vec[i]);
return 0;
}
La finalul semestrului I se reface situatia pentru serie si sunt eliminati din vector toti
studentii care s-au retras. Acestia sunt dati printr-un vector de CNP-uri. Afisati doar
studentii care au mai ramas.

typedef char tip_CNP[14];

bool s_aRetras(Student &s, tip_CNP *lista_retrasi, int cati_retrasi){


for (int i=0;i<cati_retrasi;i++)
if (strcmp(s.CNP, lista_retrasi[i])==0) return true;
return false;
}

void initializeaza(Student &s, Student &s1){


//nu eliberam spatiul pentru nume, pentru ca nu i s-a alocat inca => crash
int l = strlen(s1.nume);
s.nume = (char*)malloc(sizeof(char) * (l+1));
strcpy( s.nume, s1.nume);

strcpy(s.CNP, s1.CNP);

s.gr = s1.gr;

for (int i=Analiza; i<=Engleza; i++ ) s.note[i]=s1.note[i];


}
//main
int nr_retrasi; cout<<"cati studenti s-au retras si ce CNP-uri au? ";
cin>>nr_retrasi;

// typedef char tip_CNP[14];


tip_CNP * CNP_retrasi = (tip_CNP*)malloc(nr_retrasi*sizeof(tip_CNP));
for (int i=0; i<nr_retrasi; i++)
cin>>CNP_retrasi[i];

Student *vec_actualizat;
vec_actualizat =(Student*)malloc(sizeof(Student)*(n-nr_retrasi));

int cati_au_ramas=0;
for (int i=0; i<n; i++)
if (s_aRetras(vec[i], CNP_retrasi, nr_retrasi) == false ) {
initializeaza(vec_actualizat[cati_au_ramas],vec[i]);
cati_au_ramas++;
}

for (int i=0; i<cati_au_ramas; i++) afisez(vec_actualizat[i]);

S-ar putea să vă placă și