Accès aux champs d'une structure et affectation
Nous pouvons accéder aux champs d'une structure soit en utilisant l'identificateur d'une variable structurée soit en utilisant l'identificateur d'un pointeur vers une variable structurée à condition que ce dernier ait été correctement initialisé.
Pour accéder au champ <truc> d'une variable strcuturée <identi_var>, il faut utiliser la syntaxe :
<identi_var>.<truc>
C'est le "." qui permet d'accéder au champ à partir de l'identificateur <identi_var>.
Si on accède au champ <truc> à partir d'un identificateur <identi_pt> de variable qui pointe vers une variable structurée, alors il faut utiliser la syntaxe :
<identi_pt> -> <truc>
C'est le "->" qui permet d'accéder au champ à partir de l'identificateur <identi_pt>.
La syntaxe se différentie donc, considérons le code suivant :
#define MAX 20
struct etudiant
{
char nom[MAX], prenom[MAX];
float moyenne;
} ;
void main()
{
// déclaration de "e" et "a" : variables structurées, et "pt_e" comme variable
// de type pointeur vers variable structurée de nature "etudiant".
// seule "e" est initialisée à la déclaration.
struct etudiant e = {"jean","seigne",18.8}, a, *pt_e;
printf("%s", e.nom);
printf("%s", e.prenom); // syntaxe avec "." car nom de variable printf("%f", e.moyenne);
pt_e = &e;
//l'adresse de la variable structurée « e » est rangée dans
// la variable « pointeur vers variable structurée » « pt_e ».
printf("%s", pt_e->nom);
printf("%s", pt_e->prenom); // syntaxe avec "->" car « pointeur vers »
printf("%f", pt_e->moyenne);
}
La saisie des champs suit les mêmes règles que la saisie de variables. Exemple d'instructions :
e.moyenne = 10.0;
strcpy(e.nom, "poubot");
scanf("%s", e.prenom); // on suppose que "paul" soit saisi
A ce stade, la variable structurée « e » contiendra comme valeurs de champs : "poubot" pour le nom, "paul" pour le prénom, et 10.0 pour moyenne.
Si on effectue ensuite les instructions suivantes :
pt_e->moyenne = 19.0; // sachant que pt_e=&e comme dans le code ci-dessus
scanf("%s", pt_e->nom); // on suppose que "snoopy" soit saisi
A ce stade, la variable structurée "e" contiendra comme valeurs de champs : "snoopy" pour le nom, "paul" pour le prénom, et 19.0 pour moyenne.
Vous remarquerez que le champ "nom" correspond à l'identificateur d'un pointeur constant car c'est un tableau de caractères. Pour saisir une chaîne de caractères la fonction "scanf" attend un pointeur, et c'est bien un pointeur qu'on lui transmet.
Peu importe que l'on écrive :
« e.nom » ou « pt_e->nom »
Ce qui importe c'est ce que représente le champ.
Par contre, si l'on veut modifier caractères par caractères, alors on accède individuellement à des cases du tableau de caractères. Ainsi :
e.nom[3] = 'v';
pt_e->nom[1] = 'y';
scanf("%c", &(e.nom[2]); // on saisie 'l'
scanf("%c", &(pt_e->nom[4]) // on saisie 'e'
pt_e->nom[5] = '\0';
Si l'on affiche :
printf("%s", e.nom);
Nous obtiendrons "sylve"
En résumé, si un des champs est un tableau, il se manipule comme tel.
On peut aussi affecter une variable structurée à une autre de même nature. L'instruction :
a = e;
est possible. Elle recopie tous les champs de la variable "e", dans les champs de la variable "a" (Cf déclaration de "a" ci-dessus).
Si « a » et « e » ne sont pas des variables structurées de même nature cela provoquera une erreur. Ne pas oublier que le compilateur vérifie la concordance des types.
On peut s'interroger sur le pourquoi des deux syntaxes "." et "->" ? La raison est qu'il est plus lisible d'écrire :
pt_e->moyenne
que
(*pt_e).moyenne
Surtout dans le cas des saisies :
Il est plus lisible d'écrire :
scanf("%d",&( pt_e -> moyenne);
Que :
scanf("%d",&((*pt_e).moyenne));
Bien que ces écritures désignent la même chose pour le compilateur.