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

Leave a Reply

Your email address will not be published. Required fields are marked *