Sunteți pe pagina 1din 14

Tipuri de date definite de utiliztor

n limbajul C, utilizatorul i poate crea propiile tipuri de date, n cinci moduri diferite, astfel: - declaraia typedef asociaz un nume unui tip; - structura grupeaz mai multe obiecte (variabile) de tipuri diferite sub acelai nume; - cmpul de bii este o variant a structurii ce permite accesul mai uor la biii individuali ai unui cuvnt de memorie; - uniunea este o variant a structurii ce face posibil utilizarea n comun a unei zone de memorie de ctre mai multe obiectede tipuri diferite; - enumerarea este o list de nume de constante ntregi. Structuri Declararea unei structuri O declaraie de structur precizeaz identificatorii i tipurile elementelor componente i constituie o definiie a unui nou tip de date. Componentele unei structuri sunt denumite membrii (uneori elemente sau cmpuri) structurii. Forma general de definire a unei structuri este: struct identif_structura { tip_elem_1 identif_elem_1; tip_elem_2 identif_elem_2; tip_elem_n identif_elem_n; } lista_identif_var_tip_struct; unde: struct este cuvntul-cheie pentru structur, identif_structura este tipul de structur declarat, identif_elem_1, identif_elem_2,, identif_elem_n sunt numele variabilelor care fac parte din structur, tip_elem_1, tip_elem_2,, tip_elem_n sunt, respectiv, tipurile variabilelor care fac parte din structur, iar lista_identif_var_tip_struc este list cu variabilele de tipul identif_structura. Tipurile elementelor unei pot fi oarecare, cu excepia tipului structurii care se declar. Totui, se admit pointeri de tipul structurii respective. Exemple de declaraii de tipuri de structuri: struct data { int an, luna, zi; } zi_curs; struct date_pers { char nume[30]; char pren[20]; int varsta; struct data data_nasterii; };

71

La declararea unui tip de structur, pot s lipseasc, dar nu amndou, fie identif_structura (structur anonim) fie lista_identif_var_tip_struc. Dac numele unei structuri nu este omis, se mai pot declara i alte structuri cu declaraia: struct identif_structura lista_identif_var_tip_struct; De exemplu, variabila astazi, de tipul structur data, se poate declara astfel: struct data astazi; Observaie: n C++, cuvntul-cheie struct se poate omite, adic se poate utiliza declatraia: identif_structura lista_identif_var_tip_struct; Astfel, variabila astazi se mai poate declara i astfel: data astazi; Inializarea unei structuri Iniializarea unei variabile structur se face specificnd, ntre acolade, valori pentru toi membrii structurii, n ordinea n care acetia apar n declaraia tipului de structur. Dac un membru este de tip structur, pentru acesta, valorile se pot specifica ntre accolade sau se pot omite acoladele. De exemplu, cu tipurile structur definite anterior, se declar i iniializeaz variabilele astazi i ion: struct data astazi={2003,12,3}; date_pers ion={"Ion","Vasile",34,{1969,2,29}}; /* sau date_pers ion={"Ion","Vasile",34,1969,2,29}; */ Accesul la membrii structurii Accesul la un membru al structurii se face cu operatorul de selecie (.), dup sintaxa: identif_structur . identif_membru; De exemplu, cu structura pers, de tip date_pers, se pot efectua operaii de genul urmtor: pers.nume=Ionescu; pers.varsta=28; pers.data_nasterii.an=1985; Accesul la un element al unui membru de tip tablou se face specificn i indexul elementului membrului respective. De exemplu, referirea la caracterul 3 din membrul nume al structurii pers se face astfel: pers.nume[3] 72

Atribuiri cu structuri Cu variabilele tip structur, se pot efectua operaii de atribuire, dac variabilele sunt de acelai tip. Exemplu: struct pers { char nume[30]; int varsta; } ion,stud; stud=ion; Transmiterea structurilor ctre funcii Transmiterea structurilor sau membrilor acestora ctre funcii se poate face prin valoare sau prin adresa. Exemple: printf("%d",stud.varsta); /* transmitere valoare varsta*/ printf("%d",stud.nume[2]); /* transmitere valoare char*/ scanf("%d",&ion.varsta); /* transmitere adresa varsta*/ scanf("%d",ion.nume); /* transmitere adresa sir*/ citeste_date(&stud); /* transmitere adresa struct*/ afis_date(stud); /* transmitere valoare struct*/ Programul Structuri si functii utilizeaz funcii care opereaz cu structuri sau membrii de structuri: /* Structuri si functii */ #include <stdio.h> #include <conio.h> #include <string.h> struct data { int an, luna, zi; } zi_curs; struct date_pers { char nume[30]; char pren[20]; int varsta; struct data data_nasterii; }; data cit_data(); void afis_data(char *s, struct data p); date_pers cit_date_pers(); void afis_date_pers(date_pers p);

73

void main() { clrscr(); struct data astazi={2003,12,3}; date_pers ion={"Ion","Vasile",34,1969,2,29}; zi_curs=astazi; /* atribuire cu structuri */ /* transmitere structura catre functie*/ afis_data("Data ",zi_curs); afis_date_pers(ion); afis_date_pers(cit_date_pers()); getch(); } data cit_data() { struct data v; printf("\tan =");scanf("%d",&v.an); printf("\tluna=");scanf("%d",&v.luna); printf("\tzi =");scanf("%d",&v.zi); return v; }; void afis_data(char *s,struct data p) { printf("\t%s : %#02d.%#02d.%#04d\n",s,p.zi,p.luna,p.an); }; date_pers cit_date_pers() { date_pers v; printf("\tNume =");gets(v.nume); printf("\tPrenume=");gets(v.pren); printf("\tVarsta =");scanf("%d",&v.varsta); printf("\n\tData nasterii:\n"); v.data_nasterii=cit_data(); return v; }; void afis_date_pers(date_pers p) { printf("\n\n\tNume : %s %s\n",p.nume,p.pren); printf("\tVarsta : %d ani\n",p.varsta); afis_data("Data nasterii",p.data_nasterii); };

Tablouri de structuri Pentru a declara un tablou de structuri, mai nti se definete structura, dup care se declar tabloul cu elemente de tipul structur. De exemplu, mai jos, se declar structura note_stud i tabloul clasa cu 20 de elemente de tip note_stud:

74

struct note_stud { char nume[20]; int nota; }; note_stud clasa[20]; Pentru a avea acces la un membru al unui element al tablului, dup numele tabloului, se specific indicele ncadrat de paranteze ptrate. De exemplu, pentru a se afia membrul nota al elementului 2 al tabloului clasa, se poate utiliza instruciunea: printf(%d,clasa[2].nota); iar pentru a afia primul caracter al membrul nota al elementului 2 al tabloului clasa, se poate utiliza instruciunea: printf(%d,clasa[2].nota[3]); Pointeri la structuri Pointerii la structuri se declar, ca i n cazul celorlalte tipuri de variabile, punnd caracterul * n faa numelui variabilei de tip structur. De exemplu, n secvena urmtoare, variabila pers se declar ca pointer la structur: struct note_stud { char nume[20]; int nota; }; struct note_stud *pers, ion; Adresa unei variabile de tip structur se obine cu operatorul &, iar valoarea structurii indicate de un pointer se obine cu operatorul *. Exemple: pers=&ion; *pers=ion; Referirea la valoarea unui membru al unei structuri indicate de un pointer se face cu operatorul sgeat: ->. Acesta este format din semnele minus i mai mare ca. Exemple: printf("%s",pers->nume); printf("%d",pers->nota); Observaie: n cazul funciilor, cnd o structur se transmite prin valoare, se plaseaz n memoria stiv toat structura. Dac structura este mai complex sau conine membrii de tip tablou, acest lucru este anevoios, ceea ce duce la creterea timpului de rulare al programului. Pentru apelri rapide de funcii transmiterea trebuie s se fac prin adres, adic cu pointeri. n acest caz, n stiv, se reine doar adresa structurii. 75

Programul Pointeri la structuri utilizeaz noiunile prezentate mai sus referitoare la pointeri ce indic structuri: /* Pointeri la structuri */ #include <stdio.h> #include <conio.h> #include <string.h> struct date_pers { char nume[20]; int nota; }; struct data { int an, luna, zi; }; date_pers cit_struct(void); /* Returneaza val struct */ void afis_struct(date_pers *p); void modif_data(data *p); /* Primeste adr struct */ void afis_data(char *s,data p);/* Primeste val struct */ void cit_tab(int n, date_pers *p); void afis_tab(int n, date_pers *p); void ordonare(int n, date_pers *t); void main() { clrscr(); int n; struct data *azi, zi_init={2003,12,2}; azi=&zi_init; afis_data("Data initiala ",*azi); printf("n=");scanf("%d",&n); struct date_pers cls[20]; cit_tab(n,cls); ordonare(n,cls); modif_data(azi); afis_data("Data ",*azi); afis_tab(n,cls); getch(); } date_pers cit_struct() { date_pers v; printf("Nume : ");scanf("%s",v.nume); printf("Nota : ");scanf("%d",&v.nota); return v; }

76

void afis_struct(date_pers *p) { printf("%-20s",p->nume); printf("%-4d\n",p->nota); } void modif_data(data *p) { data v; clrscr(); printf("Actualizati data:\n"); printf("an : ");scanf("%d",&v.an); printf("luna : ");scanf("%d",&v.luna); printf("zi : ");scanf("%d",&v.zi); *p=v; } void afis_data(char *s,struct data p) { clrscr(); printf("%s : %#02d.%#02d.%#04d\n",s, p.zi,p.luna,p.an); } void cit_tab(int n, date_pers *p) { int i; for (i=0;i++<n;p++) { clrscr(); *p=cit_struct(); } } void afis_tab(int n, date_pers *p) { int i; printf("%-20s%-4s\n\n","Nume","Nota"); for (i=0;i++<n;) afis_struct(p++); } void ordonare(int n, date_pers *t) { int i,j; struct date_pers x; for (i=0;i<n-1;i++) for (j=0;j<n-i-1;j++) if (strcmp(t[j].nume,t[j+1].nume)>0) { x=t[j]; t[j]=t[j+1]; t[j+1]=x; } }

77

Cmpuri de bii Limbajul C ofer posibilitatea de a structura datele la nivel de bit. Astfel, unor membrii de structuri sau uniuni, li se pot aloca, dintr-un octet, biti individuali sau grupuri de bii. n felul acesta, se definesc cmpuri de biti care pot fi accesate fiecare, separate de restul octetului, pentru evaluare i/sau modificare. Forma general de definire a unei structuri cu membrii de tip cmp de bii este: struct identif_structura { tip_elem_1 identif_elem_1 : lungime ; tip_elem_2 identif_elem_2 : lungime; tip_elem_n identif_elem_n : lungime; } lista_identif_var_tip_struct; unde prin lungime este specificat numrul de bii dintr-un cmp. Pentru cmpurile de bii exist urmtoarele restricii: tipul poate fi int, signed sau unsigned; lungime este o constant ntreag cu valori ntre 0 i 15; nu se poate evalua adresa unui cmp de bii; nu se pot organiza tablouri de cmpuri de bii; - nu se poate ti cum sunt rulate cmpurile (de la dreapta la stnga sau invers, funcie de echipament). Cmpurile de bii pot fi utile atunci cnd informaia furnizat de anumite echipamente este transmis prin octet sau atunci cnd se dorete accesul la biii unui octet sau atunci cnd memoria este limitat i anumite informaiii pot fi stocate ntr-un singur octet. De exemplu, pentru analiza intrrii de la un echipament hard (cum ar fi portul de stare de la un adaptor de comunicaie), un octet de stare poate fi organizat astfel: Bit 0 1 2 3 4 5 6 7 Semnificaie (dac vloarea bitului este 1) Modificare n linia Clear to send Modificare n linia Data set ready Detectare de font cresctor Modificare n linia de recepie Clear to send (CTS) Data set ready (DST) Apel telefonic Semnal recepionat

Informaia dintr-un astfel de octet de stare poate fi reprezentat utiliznd urmtorul structur de cmpuri de bii: struct organizare_stare { unsigned modif_cts: unsigned modif_dsr: 78

1; 1;

unsigned detect_front: unsigned modif_rec: unsigned cts: unsigned dsr: unsigned apel: unsigned rec_line: } stare_octet;

1; 1; 1; 1; 1; 1;

Referirea la un cmp de bii se face ca la orice membru al unei structuri, cu ajutorul operatorilor punct (selectare direct) sau sgeat (selectare indirect). Exemplu: stare_octet.apel=0; Numele cmpului de bii poate s lipseasc. n acest caz, biii sunt alocai conform specificaiei lungime, dar nu pot fi utilizai deoarece nu pot fi accesai. De exemplu, dac se definete stuctura: struct organizare_redusa_stare { unsigned 4; /* biti neutilizati */ unsigned cts: 1; unsigned dsr: 1; /* 2 biti nespecificati */ } stare_octet; accesul la biii cts i dsr se face mai uor, deoarece se sare peste bii neutilizai. Biii neutilizati, situai dup ultimul camp de bii utilizat (dsr, n cazul exemplului), nu este nevoie s fie specificai. ntr-o structur, se pot amesteca membrii normali cu cmpuri de bii. struct date_pers { char nume[50]; struct adr adresa; unsigned casatorit: 1; unsigned plata: 1; unsigned bursa: 1; } student; Cmpurile de bii se pot iniializa ca orice alt membru al structurii. Pentru biii neutilizati nu se specific valori. Programul urmtor ilustreaz modul de alocare a memorie, n cazul structurilor cu cmpuri de bii: /* Campuri de biti */ #include <stdio.h> #include <conio.h> typedef struct { unsigned char adr; 79

unsigned :1; unsigned cts:3; unsigned dsr:2; unsigned int lung; unsigned char *data; } campuri; void main() { clrscr(); campuri exemplu={0xAB,3,2,0xABCD,0}; char *text[]={ "adr=", "2n+2dsr+3cts+1n=", "lungime="," ", "adr data="," "}; char *p; int i,j,k; exemplu.data=&exemplu.adr; printf(" Membrii variabilei exemplu:\n"); printf("adr=%x\n",exemplu.adr); printf("cts=%d\n",exemplu.cts); printf("dsr=%d\n",exemplu.dsr); printf("lungime=%x\n",exemplu.lung); printf("adr data=%p\n",exemplu.data); printf("\n\n Afisare in binar var exemplu: "); printf(" %d octeti\n",k=sizeof(exemplu)); p=(char*)&exemplu;/* Adr prim octet */ for(i=0; i<k; i++,p++) { printf("adr=%p %s",p,text[i]); for(j=7; j>=0; j--) printf("%d",(*p>>j)&1); /* afiseaza bit j */ printf("\n"); } getch(); } Uniuni O uniune este o locaie de memorie care este mprit, n momente diferite, de dou sau mai multe variabile, n general, de tipuri diferite. Sintaxa declaraiei unei uniuni este similar cu cea a structurii: union identif_structura { tip_elem_1 identif_elem_1; tip_elem_2 identif_elem_2; tip_elem_n identif_elem_n; } lista_identif_var_tip_uniune;

80

unde identificatorii declarai ca membrii reprezint nume cu care sunt referite obiectele de tipuri diferite care utilizeaz n comun zona de memorie. Spaiul de memorie alocat corespunde tipului de dimensiune maxim. De exemplu, n secvena: union tip_u { char c; int i; } var_u; spaiul de memorie alocat pentru variabila uniune var_u este de 2octei. Tipurile uniune ofer posibilitatea unor conversii interesante, deoarece aceeai zon de memorie poate conine informaii organizate n moduri diferite, corespunztoare tipurilor membrilor. De exemplu, n programul Uniuni, n doi octei se memoreaz pe rnd un caracter i un ntreg, dup care se afieaz coninutul fiecrui octet. /* Uniuni */ #include <stdio.h> #include <conio.h> union tip_u { char c; int i; }; void tipareste( union tip_u x, char *p); void main() { clrscr(); union tip_u u; u.c='A'; tipareste(u, (char *)&u.c); u.i=22610; tipareste(u, (char *)&u.c); getch(); } void tipareste( union tip_u x, char *p) { printf("caracter=%c (%#x)\n",x.c,x.c); printf("intreg =%d (%#x)\n",x.i,x.i); printf("adr =%p val=%#x\n",p,*p); p++; printf("adr =%p val=%#x\n",p,*p); } Membrul unei uniuni poate fi de tip structur, cu sau fr cmpuri de bii. De exemplu, n secvena urmtoare tipul uniune tip_u conine un membru s, de tip structur cu camp de bii: 81

struct tip_s { char s[10]; unsigned a:2; unsigned b:4; int k; }; union tip_u { struct tip_s s; char c; int i; }; Tipul enumerare Tipul enumerare const dintr-un ansamblu de constante ntregi, ansamblu n care fiecare constant este asociat unui identificator. Declararea tipului enumerare se face dup sintaxa: enum id_tip_enum{lista_enumerri} lista_id_var_enum; unde: - id_tip_enum este numele generic al tipului enumerare i este opional; - lista_enumerri este format din identificatorii elementelor separai prin virgul i, opional, urmai de semnul egal i o constant de iniializare; - lista_id_var_enum este o list de variabile de tipul id_tip_enum i este opional. Poate lipsi fie numele tipului (tip anonim), fie lista de variabile. n declaraia urmtoare, se definete tipul enumerare studii i se declar variabila niv_sutd, care poate lua numai valorile elem, medii i sup: enum studii{elem,medii,sup} niv_stud; Se observ c declaraia const n enumerarea tuturor valorilor posibile pentru tipul respectiv. Fiecare simbol ine locul unei valori ntregi. Dac nu se face iniializarea ssimbolurilor, atunci valorile acestora sunt stabilite implicit: primul simbol are valoarea 0, iar urmtorii au o valoare mai mare cu o unitate dect precedentul. n cazul exemplului de mai sus, valorile simbolurilur sunt stabilite implicit astfel: elem=0, medii=1 i sup=2. Dac se face iniializarea unora dintre simboluri, atunci valorile lor se pot modifica explicit. De exemplu, declaraia: enum studii{elem=8,medii=12,sup}; modific valorile simbolurilur astfel: elem=8, medii=12 i sup=13. Observaie: Tipul boolean, existent n Pascal, se poate introduce i n C cu declaraiia:

82

enum boolean{false,true}; sau, mai convenabil, cu declaraiia: typedef enum{false,true} boolean; n acest caz, valorile simbolurilur sunt: false=0 i true=1. Variabilelor de tip enumerare li se pot atribui numai valorile declarate. Tiprirea lor este posibil numai ca numere ntregi i nu ca iruri., dup cum se poate vedea n secvena: enum studii{elem,medii,sup}; enum studii elev=medii; printf("elev=%d\n",elev);/* rezulta, elev=1*/ printf("elev=%s\n",elev);/* Gresit*/ Identificatorii elementelor tipului enumerare pot fi afiai cu ajutorul unui tablou de iruri de caractere, atunci cnd elementele nu sunt iniializate, sau cu o instruciune switch, n orice situaie. Acest aspect este scos n eviden n programul urmtor: /* Enumerare*/ #include <stdio.h> #include <conio.h> enum studii_1 {elem=8,med=12,sup} nivel; void main() { clrscr(); enum studii_1 elev=med; printf("elev=%d\n\n",elev);/* rezulta, elev=1 */ printf("Elemente neinitializate\n"); enum studii_2 {elementare,medii,superioare} niv; char std[][12]={"elementare", "medii ", "superioare"}; for(niv=elementare;niv<=superioare;niv++) printf("%s=%d\n",std[niv],niv); printf("\n\n"); printf("Elemente initializate\n"); for(nivel=elem;nivel<=sup;nivel++) switch (nivel) { case elem: printf("elem=%d\n",nivel);break; case med : printf("med =%d\n",nivel);break; case sup : printf("sup =%d\n",nivel); }; 83

getch(); } Dup cum se constat, programul devine mai clar i mai uor de urmrit, deoarece tipul enumerare faciliteaz operarea cu variabile care pot lua un numr redus de valori ntregi, valori crora li se asociaz cte un nume sugestiv. Declaraia typedef Forma general a declaraiei typedef este urmtoarea: typedef tip nume_nou; unde tip este un tip valid de date iar nume_nou este un nou nume pentru tipul respectiv. Cu alte cuvinte, cu declaraia typedef nu se creaz un tip nou ci se definete un nume nou, pentru un tip existent. De exemplu, n secvena urmtoare, pentru tipul float se creaz dou nume noi real i simpla_precizie: typedef float real; typedef real simpla_precizie; Prin definirea propiilor nume pentru tipurile de date utilizate ntr-un program, acesta poate fi citit mai uor i i se mrete portabilitatea, adic programul nu mai depinde de echipament. La compilarea ntr-un mediu nou, se vor modifica numai declaraiile typedef.

84

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