UNIUNE
Limbajul C oferă utilizatorului posibilitatea de a folosi aceeaşi zonă de memorie pentru a păstra date de tipuri diferite în momente diferite ale execuţiei programului. Astfel, de exemplu, putem utiliza o zonă de memorie pentru a păstra la un moment dat o dată flotantă, iar ulterior să reutilizăm aceeaşi zonă pentru o dată întreagă sau de tip pointer. Reutilizările zonelor de memorie conduc la utilizarea mai eficientă a acesteia, uneori putându-se obţine o economie substanţială a spaţiului de memorie alocat programului.
O uniune se declară printr-o construcţie asemănătoare declaraţiei de structură. Deosebirea constă în înlocuirea cuvântului struct prin union:
union nume
{ tip_membru_1;
. . .
tip_membru_2;
}
Exemplu:
union u
{ int i;
float f;
double d;
};
Prin această declaraţie s-a definit tipul de date u. În continuare, putem declara date de tipul u printr-o declaraţie de forma:
union u u1;
unde u1 este o dată de tip u căreia i se alocă o zonă de memorie care poate fi utilizată pentru a păstra date de tipurile int, float sau double. Deoarece tipul double necesită memoria cea mai mare se alocă 8 octeţi. Astfel zona u1 poate păstra pe oricare din celelalte componente ale uniunii dar în momente diferite ale execuţiei programului.
Accesul la componentele unei uniuni se face la fel ca şi în cazul structurilor. Astfel, pentru a ne referi la componenta i a uniunii u1 definită în exemplul anterior folosim construcţia:
u1.i
sau dacă p este pointer spre tipul u declarat prin
union u *p;
atunci construcţia
p -> i
permite accesul la componenta i a uniunii spre care pointează p.
Pentru a evita erorile legate de evidenţa în fiecare moment a datei care se prelucrează se ataşează unei uniuni o dată menită să indice componenta curentă. Această dată este specificată pentru fiecare uniune. De exemplu pentru uniunea u1 definită anterior este important să se ştie dacă zona de memorie conţine un întreg, un flotant în simplă precizie sau un flotant în dublă precizie. Se definesc trei constante simbolice:
#define INTREG 1
#define F_SIMPLU 2
#define F_DUBLU 3
Modificăm tipul u ataşând data tip_curent de tip int astfel:
struct u
{int tip_curent;
union { int i;
float f;
double d;
} uu;
};
Declarăm structura us astfel:
struct u us;
În acest caz, în momentul în care se păstrează o dată în zona rezervată uniunii, se atribuie componentei tip_curent una din constantele definite anterior:
INTREG, dacă se păstrează un întreg;
F_SIMPLU dacă se păstrează un flotant în simplă precizie;
F_DUBLU dacă se păstrează un flotant în dublă precizie.
Astfel când se foloseşte componenta de tip int se va asocia atribuirea:
us.tip_curent=INTREG;
Analog se vor folosi ţi atribuirile următoare când se vor folosi componentele de tip float sau de tip double:
us.tip_curent=F_SIMPLU;
respectiv:
us.tip_curent=F_DUBLU;
În felul acesta, se poate testa, în fiecare moment, tipul de dată prezent în zona rezervată. Aceasta se poate face printr-o secvenţă de instrucţiuni if sau prin intermediul instrucţiunii switch.
if (us.tip_curent = = INTREG) // se foloseste us.uu.i
else if (us.tip_curent = = FSIMPLU) // se foloseste us.uu.f
else if (us.tip_curent = = FDUBLU) // se foloseste us.uu.d
else eroare
sau folosind switch avem o construcţie mai clară de forma:
switch (us.tip_curent)
{ case INTREG:
// se foloseste us.uu.i
break;
case FSIMPLU:
// se foloseste us.uu.f
break;
case FDUBLU
// se foloseste us.uu.d
break;
default:
// eroare
}
Programul următor calculează ariile pentru următoarele figuri geometrice:
cerc;
dreptunghi;
pătrat;
triunghi.
Programul citeşte datele pentru o figură geometrică, calculează aria figurii respective şi scrie rezultatul:
La intrare se folosesc următoarele formate:
– pentru cerc C raza;
– pentru dreptunghi D lungime laţime;
– pentru pătrat P latură;
– pentru triunghi T latură latură latură;
– sfârşit fişier EOF.
În cazul triunghiului, se utilizează formula lui HERON pentru calculul ariei:
aria = sqrt (p*(p-a)(p-b)(p-b))
unde p este semiperimetrul, iar a, b, c sunt cele 3 laturi.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
#define EROARE -1
#define CERC 1
#define PATRAT 2
#define DREPT 3
#define TRIUNGHI 4
typedef struct
{ int tip; // tipul figurii
union
{ double raza // cerc
double lp ; // patrat
double ld[2] ; // dreptunghi
double lt[3] ; // triunghi
} fig;
}FIG;
void main (void) // calculeaza arii
{
double aria,p;
int i;
char car[2];
FIG zfig;
for(; 😉 // citeste primul caracter,el defineste tipul figurii geometrice
{ printf(“se cere o litera mare\n”);
if ((i = scanf(“%1s”,car)) == EOF) break;
if (i != 1)
{ printf (” se cere o litera mare\n”);
continue;
}
zfig.tip = EROARE;
switch(car[0])
{case ‘C’: // cerc
printf(“se cere raza cercului in flotanta\n”);
i = scanf(“%lf”, &zfig.fig.raza);
if(i != 1)
{ printf(“se cere raza cercului in flotanta\n”);
break;
}
zfig.tip = CERC; // se pastreaza tipul figurii
break;
case ‘P’: // patrat
printf(“se cere latura patratului in flotanta\n”);
i = scanf(“%lf”,&zfig.fig.lp);
if( i !=1)
{ printf(“se cere latura patratului in flotanta\n”);
break;
}
zfig.tip = PATRAT;
break;
case ‘D’: // dreptunghi
printf(“se cer laturile dreptunghiului in flotanta\n”);
i = scanf(“%lf %lf”,&zfig.fig.ld[0],&zfig.fig.ld[1]);
if(i != 2)
{ printf(“se cer laturile dreptunghiului in flotanta\n”);
break;
}
zfig.tip = DREPT;
break;
case ‘T’: // triunghi
printf(“se cer laturile triunghiului in flotanta\n”);
i = scanf(“%lf %lf %lf”, &zfig.fig.lt[0], &zfig.fig.lt[1],&zfig.fig.lt[2]);
if(i != 3)
{ printf(“se cer laturile triunghiului in flotanta\n”);
break;
}
zfig.tip =TRI;
break;
printf(“laturile nu formeaza un triunghi\n”);
break;
default:
printf(“se cere una din literele urmatoare\n”);
printf(“C pentru cerc\n”);
printf(“P pentru patrat\n”);
printf(“D pentru dreptunghi\n”);
printf(“T pentru triunghi\n”);
} // sfarsit switch
switch (zfig.tip)
{case CERC: // aria cercului
printf(“raza=%g aria=%g\n”, zfig.fig.raza, PI*zfig.fig.raza*zfig.fig.raza);
break;
case PATRAT: // aria patratului
printf(“latura =%g aria=%g\n”,zfig.fig.lp, zfig.fig.lp*zfig.fig.lp);
break;
case DREPT: // aria dreptunghiului
printf(“lungimea =%g latimea =%g\n”, zfig.fig.ld[0], zfig.fig.ld[1]);
printf(“aria=%g\n”, zfig.fig.ld[0]*zfig.fig.ld[1]);
break;
case TRIUNGHI: // aria triunghiului
p=(zfig.fig.lt[0] + zfig.fig.lt[1] + zfig.fig.lt[2])/2;
if(p>zfig.fig.lt[0] && p>zfig.fig.lt[1] && p>zfig.fig.lt[2])
{p=p*(p-zfig.fig.lt[0])*(p-zfig.fig.lt[1])* (p-zfig.fig.lt[2]);
printf(“a=%g b=%g c=%g\n”, zfig.fig.lt[0], zfig.fig.lt[1], zfig.fig.lt[2]);
printf(“aria = %g\n”,sqrt(p));
}
else { printf (“ laturile nu formeaza un triunghi”);
break;
}
default : // avans pana la newline sau EOF
while ((i = getchar()) != ‘\n’ && i != EOF);
} // sfarsit switch
if (i = = EOF) break;
} // sfarsit for
} // sfarsit main