Lucrarea de laborator nr. 9
TIPURILE DE DATE STRUCTURĂ,
UNIUNE ŞI ENUMERARE
1. Conţinutul lucrării
În lucrare sunt prezentate tipurile definite de utilizator structură, uniune şi enumerare, accesul la componentele lor şi asignarea de nume pentru aceste tipuri.
2. Consideraţii teoretice
2.1. Tipul de date "structură"
O structură conţine mai multe componente de tipuri diferite (predefinite sau definite de utilizator), grupate conform unei ierarhii.
Declaraţia unei structuri se poate face astfel:


Observaţie: În aceasta declaraţie nu pot lipsi simultan "nume" şi “identificator_variabilă”.
O variabilă structură de tipul "nume" poate fi declarată şi ulterior conform diagramei de mai jos, cu menţiunea că cuvântul cheie "struct" poate lipsi în C++:
Exemple echivalente:
a) struct material {
long cod;
char den [30];
char um [10];
real cantitate;
real pret_unit;
} stofa, hartie, motor;
b) struct material{
long cod;
char den [30];
char um [10];
real cantitate;
real preţ_unitar;
};
struct material stofa, hartie, motor;
sau
material stofa, hartie, motor;
c) struct {
long cod;
char den [30]
char um [10];
real cantitate;
real pret_unitar;
} stofa, hartie, motor;
Accesul la componentele unei structuri se poate face prin procedeul de calificare:
identificator_variabilă.identificator_câmp;
Exemplu: stofa.den
hartie.cantitate
Procedeul de calificare pătrunde din aproape în aproape în ierarhia structură.
În limbajul C, transmiterea ca parametru a unei structuri la apelul unei funcţii, se face numai prin adresa variabilei de tip structură. De exemplu:
void f (struct material *p, ...);
Apelul se va face prin:
f(&stofa, ...)
În funcţie, selectarea unui câmp se face astfel:
(*p).den
(*p).cantitate
sau înlocuind (*p). prin p-> , ca mai jos:
p->den
p->cantitate
În limbajul C++, o structură poate fi transferată prin parametri în 3 moduri:
- direct: void f (material p, ..)
- pointer spre structură: void f (material *p, ...)
- referinţă la structură: void f (material &p, ...)
O structură de acelaşi tip se poate atribui direct una alteia:
material alfa, beta;
alfa=beta; {este corect}
2.2. Tipul de date "uniune"
În momente diferite ale execuţiei, se pot păstra în aceeaşi zonă de memorie date de tipuri diferite pentru economisirea memoriei sau din motive ale concepţiei programului. Acest lucru se face grupând toate datele care se alocă în aceeaşi zonă de memorie. Structura utilizator obţinută se numeşte uniune. Sintaxa uniunii este identică cu cea a structurii, singura deosebire constând în înlocuirea cuvântului cheie "struct" cu "union" în diagramele de sintaxă de la punctul 2.1.
De menţionat că zona de memorie rezervată are dimensiunea componentei care necesită cea mai multă memorie pentru reprezentare.
Accesul la componente se face identic ca la structură.
De menţionat că programatorul trebuie să cunoască în fiecare moment care dată este reprezentată.
Exemplu:
union alfa {
char c[5]; /* reprezentare pe 5 octeţi */
int i; /* reprezentare pe 2 octeţi */
long j; /* reprezentare pe 4 octeţi */
};
union alfa x;
strcpy(x.c, “ABCD”);
Variabila x are reprezentarea în hexazecimal, astfel:
|
41 |
42 |
43 |
44 |
00 |
Daca se accesează componenta x.i, atunci aceasta va avea 4241 în hexazecimal, adică 16961 în zecimal.
În schimb, aceeaşi zonă de memorie interpretată ca x.j (long) va avea valoarea 44434241 în hexazecimal, adică 1.145.258.561 în zecimal
2.3. Tipul de date "enumerare"
Tipul enumerare permite programatorului de a folosi nume sugestive pentru valori numerice. Diagrama de sintaxă pentru tipul enumerare este asemănătoare cu tipurile structură şi uniune. Deosebirea constă în faptul că lista de componente este formată numai din identificatori de valoare întreagă 0,1,2,...:
Exemple echivalente:
a) enum săpt {luni, marţi, miercuri, joi, vineri, sâmbătă, duminică};
enum săpt săpt_vacanţă;
b) enum săpt {luni, marţi, miercuri, joi, vineri, sâmbătă, duminică}
săpt_vacanţă;
c) enum {luni, marţi, miercuri, joi, vineri, sâmbătă, duminică} săpt_vacanţă;
Atribuiri posibile:
săpt_vacanţă=vineri;
Identificatorii luni, marţi,…, au valorile 0,1,.…
2.4. Declararea tipurilor de date prin nume simbolice
În limbajul C/C++ se poate atribui un nume simbolic unui tip predefinit sau unui tip utilizator. Diagrama de sintaxă pentru asignarea unui nume simbolic "nume_tip" unui "tip" predefinit sau utilizator este următoarea:
Exemplu:
a) typedef struct {
int i;
float j;
double x;
} ALFA;
ALFA y, z;
b) typedef struct {
float re;
float im;
} COMPLEX;
COMPLEX x, y;
c) typedef union {
char x[10];
long cod;
} BETA;
BETA u, v;
d) typedef enum {false, true} BOOLEAN;
BOOLEAN k, l;
2.5. Exemple de programe
Programul următor prezintă operaţii asupra numerelor complexe, folosind tipul structură. Sunt ilustrate toate posibilităţile de transmiterea a parametrilor de tip structură.
/*Programul L9Ex1.cpp */
#include <stdio.h>
#include <conio.h>
#include <process.h>
typedef struct {float re,im;}COMPLEX;
void aduna(COMPLEX *a,COMPLEX *b,COMPLEX *c)
/* transmiterea parametrilor prin pointeri */
{
c->re=a->re+b->re;
c->im=a->im+b->im;
};
void scade(COMPLEX a,COMPLEX b,COMPLEX *c)
/* transmiterea parametrilor prin valoare "posibil numai in C++"
si a rezultatului prin pointer */
{
c->re=a.re-b.re;
c->im=a.im-b.im;
};
void produs(COMPLEX a,COMPLEX b,COMPLEX &c)
/*transmiterea parametrilor prin valoare "posibil numai in C++"
si a rezultatului prin referinta */
{
c.re=a.re*b.re-a.im*b.im;
c.im=a.im*b.re+a.re*b.im;
};
void impartire(COMPLEX *a,COMPLEX *b,COMPLEX *c)
/*transmiterea parametrilor prin pointeri */
{
float x;
x=b->re*b->re+b->im*b->im;
if (x==0) {
printf("\nÎmpartire la zero!\n");
exit(1);
}
else{
c->re=(a->re*b->re+a->im*b->im)/x;
c->im=(a->im*b->re-a->re*b->im)/x;
}
};
void main(void)
/* Operaţii asupra numerelor complexe */
{
COMPLEX a,b,c;
char ch,op;
ch='D';
while ((ch=='D')|| (ch=='d'))
{
printf("\nIntroduceti primul număr complex\n");
printf("a.re=");scanf("%f",&a.re);
printf("a.im=");scanf("%f",&a.im);
printf("\nIntroduceţi al doilea număr complex\n");
printf("b.re=");scanf("%f",&b.re);
printf("b.im=");scanf("%f",&b.im);
aduna(&a,&b,&c);
printf("\n(%f+j*%f)+(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
scade(a,b,&c);
printf("\n(%f+j*%f)-(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
produs(a,b,c);
printf("\n(%f+j*%f)*(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
impartire(&a,&b,&c);
printf("\n(%f+j*%f)+(%f+j*%f)=%f+j*%f\n",
a.re,a.im,b.re,b.im,c.re,c.im);
printf("\nCONTINUAŢI?DA=D/d,Nu=alt caracter " );
scanf("%*c%c",&ch);
}
}
Programul următor prezintă operaţii asupra datelor de tipul "union":
/* Programul L9Ex2.cpp */
#include <stdio.h>
#include <conio.h>
#include <string.h>
/* Exemplu de folosire a tipului "union" */
void main()
{typedef union{
char ch[10];
int x;
long y;
float f;
} alfa;
alfa a;
strcpy(a.ch,"ABCDEFGHI");
printf("\nDimensiunea zonei de memorie rezervata =%d octeti\n",
sizeof a);
printf("\nCONTINUTUL ZONEI:\n");
printf("\n-sir de caractere: %s",a.ch);
printf("\n-intreg de tipul int: %d(%x in hexa)",a.x,a.x);
printf("\n-intreg de tipul long: %ld(%lx in hexa)",a.y,a.y);
printf("\n-real de tipul float: %g",a.f);
getch();
}
Programul urmator prezinta operatii asupra datelor de tipul "enum".
/* Programul L9Ex3.cpp */
#include <stdio.h>
#include <conio.h>
/* Exemplu de folosire a tipului "enum" */
void main()
{
typedef enum{zero,unu,doi,trei,patru,cinci} NR;
NR x,y;
int z,w;
x=doi; /* x=2 */
y=trei; /*x=3*/
z=x+y;
w=x*y;
printf("\nz=%d w=%d\n",z,w);
getch();
x=2;y=3;/* o astfel de atribuire indica "warning" */
z=x+y;w=x*y;
printf("\nz=%d w=%d\n",z,w);
getch();
}
3. Mersul lucrării
3.1. Folosind tipul structură pentru o dată curentă an, lună, zi, să se scrie un program pentru a afişa a câtea zi din an este ziua respectivă şi câte zile au mai rămas până la sfârşitul anului.
3.2. Folosind tipul structură pentru data de naştere a D-voastră şi ştiind că în anul curent vă aniversaţi ziua de naştere în ziua de x [luni, marţi, ..., duminică], scrieţi un program pentru a afişa ziua (din săptămână) în care v-aţi născut.
3.3. Să se scrie un program modularizat care citeşte datele legate de studenţii unei grupe: nume, data naşterii, adresa şi îi afisează în ordine crescătoare lexicografică.
3.4. Să se scrie un program pentru calculul valorii unui polinom de gradul n cu coeficienţi complecşi pentru o valoare complexă. Calculul se va face cu ajutorul unei funcţii.
3.5. Să se introducă tipul RAŢIONAL ca o structură formata din numărător şi numitor. Să se scrie funcţii de simplificare, adunare, scădere, înmulţire, împărţire, ridicare la putere.
3.6. Folosind tipul uniune, care conţine câmpurile necesare pentru a putea reprezenta un cerc, un dreptunghi, un pătrat, un triunghi, să se scrie o funcţie pentru a calcula aria figurii respective.
3.7. Folosind tipul enumerare, să se introducă tipul boolean. Să se scrie o funcţie de ordonare crescătoare a unui şir folosind metoda bulelor şi un semafor de tipul boolean.
3.8. Se citeşte un şir de caractere format din litere şi cifre. Să se indice frecvenţa de apariţie a caracterelor întâlnite în şir folosind o listă ordonată alfabetic (nodul conţine caracterul, frecvenţa şi adresa următorului nod).