10.2. Accesul la elementele unei structuri

2019/03/24 in Programare in C

Fie tipul utilizator data_calendaristica definit in paragraful precedent:

struct data_calendaristica {
  int zi;
  char luna[11];
  int an;
};

si variabila dc de tip data_calendaristica:

struct data_calendaristica dc;

Data dc are trei componente:

zi, luna si an care sunt date elementare.

Se pune problema accesului (referirii) la componentele structurii dc.

Referirea la componentele unei structuri se face utilizand atat numele structurii cat si al componentei respective. Aceasta se realizeaza printr-o constructie de forma:

nume.nume1

unde:

nume este numele structurii;
nume1 este numele componentei la care se doreste sa se faca acces.

In exemplul de mai sus, vom avea acces la componenta zi a structurii dc, prin constructia:

dc.zi

In mod analog:

dc.an

ne asigura accesul la componenta an a structurii dc. Datele dc.zi si dc.an sunt de tip int

Constructia dc.luna este un pointer spre caractere si permite accesul la componenta luna a structurii dc.

Punctul (.) utilizat intr-o constructie de forma (1) nume.nume1 se considera un operator si el are prioritate maxima, la fel ca si operatorii paranteza.

O constructie de forma (1) se spune ca este un nume calificat.

Exemple:

  1. struct data_calendaristica {
      int zi;
      char luna[11];
      int an;
    };
    struct data_calendaristica dc, d[10];
      ...
      dc.zi = 1;
      dc.an = 1995;
      strcpy(dc.luna, "septembrie");
      ...
      d[3].zi = dc.zi;
      d[3].an = dc.an;
      strcpy(d[3].luna, dc.luna);
      ...
    

    Primele trei instructiuni atribuie structurii dc data calendaristica 1 septembrie 1995.

    Ultimele trei instructiuni atribuie elementului d[3] valorile componentelor structurii dc, deci elementul respectiv va pastra aceeasi data calendaristica.

  2. struct data_calendaristica {
      int zi;
      char luna[11];
      int an;
    };
    
    struct date_pers {
    char nume[50];
    char prenume[50];
    long cod;
    struct data_calendaristica data_nasterii, data_angajarii;
    };
    
    struct date_pers angajat, sectie[100];
    strcpy(angajat.nume, "Popescu");
    strcpy(angajat.prenume, "Gheorghe");
    angajat.cod = 123456789;
    

    Pentru a defini data nasterii va trebui sa folosim o dubla calificare:

    angajat.data_nasterii.zi = 3;
    strcpy(angajat.data_nasterii.luna, "august");
    angajat.data_nasterii.an = 1970;
    

    In mod analog se defineste data angajarii:

    angajat.data_angajarii.zi = 15;
    strcpy(angajat.data_angajarii.luna, "septembrie");
    angajat.data_angajarii.an = 1993;
    

In limbajul C structurile nu se pot transfera prin parametri, ci numai pointerii spre ele. Asa de exemplu, structura angajat poate fi prelucrata de functia f, daca aceasta se apeleaza cu parametrul efectiv &angajat (adresa de inceput a zonei de memorie alocata structurii angajat):

f(&angajat);

Functia f are ca parametru un pointer spre tipul structurii angajat, adica spre tipul date_pers.

Rezulta ca functia f are antetul:

void f(struct date_pers *p)

Intr-adevar, declaratia lui p specifica faptul ca el are ca valoare adresa de inceput a unei zone de memorie in care se pastreaza date de tip date_pers. Ori &angajat este chiar o astfel de adresa.

Problema care se pune in continuare este aceea a accesului la componentele structurii transferate prin adresa ei. In cazul de fata se pune problema de a avea acces, in corpul functiei f, la componentele structurii angajat: (nume, prenume etc.)

In corpul functiei f nu se pot utiliza numele calificate:

angajat.nume, angajat.prenume, angajat.data_nasterii etc.

deoarece nu este cunoscut numele structurii angajat. In locul numelui structurii se cunoaste pointerul spre ea: p. De aceea, in constructiile de mai sus nu avem decat sa inlocuim numele angajat cu *p. Se vor obtine constructiile:

(*p).nume;
(*p).prenume;
(*p).data_angajarii.zi;
etc.

Pentru a simplifica scrierea constructiilor de acest fel s-a introdus o notatie cu sageata (-> minus urmat de caracterul mai mare) si anume: (*p). se inlocuieste cu p->.

In felul acesta, constructiile de mai sus se scriu mai simplu:

p->nume;
p->prenume;
p->data_angajarii.zi;
etc.

Sageata, ca si punctul, se considera un operator de prioritate maxima, la fel ca si parantezele. Amintim ca acesti operatori se asociaza de la stanga spre dreapta.

In concluzie, accesul la componentele unei structuri se realizeaza fie printr-o constructie de forma:

nume.nume1

fie prin:

pointer -> nume1

unde:

nume este numele structurii;
nume1 este numele componentei;
pointer este un pointer spre structura.

10.3. Asignari de nume pentru tipuri de date (declaratii de tip)