0% ont trouvé ce document utile (0 vote)
59 vues45 pages

Struct

Le document présente les types composés en programmation, notamment les structures, unions et énumérations. Les structures permettent de regrouper des valeurs de types différents, tandis que les unions partagent la même zone mémoire pour différents types. Les énumérations définissent un type par une liste de valeurs possibles, facilitant ainsi la gestion des constantes.

Transféré par

sanae.batrich.05
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
59 vues45 pages

Struct

Le document présente les types composés en programmation, notamment les structures, unions et énumérations. Les structures permettent de regrouper des valeurs de types différents, tandis que les unions partagent la même zone mémoire pour différents types. Les énumérations définissent un type par une liste de valeurs possibles, facilitant ainsi la gestion des constantes.

Transféré par

sanae.batrich.05
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Les types composés : struct, union &

enum
Les types composés : structures
Syntaxe
Déclaration de nouveau type de structure :
struct nomStruct{
type1 champ1;
type1 champ2;
...
typeN champN;
};

Déclaration de variable structurée de type structure nomStruct (préalablement défini) :


struct nomStruct variable;

Définition
• Une structure (ou enregistrement) est une suite finie d’éléments de types différents,
• Chaque élément de la structure, appelé : membre ou champ, est désigné par un
identificateur,
• Elle permet de grouper plusieurs valeurs dans une seule variable.
12/12/2024 80
Les types composés : structures
Exemple
compte = numBanque + numCompte + solde
• La structure compte est composée de champs :
• nommés : banque, compte, solde
• et typés : int pour numBanque et numCompte, float pour solde
• Les différents éléments d’une structure n’occupent pas nécessairement des
zones contigues en mémoire (Contrairement aux tableaux).

Déclaration de type structure compte :


struct compte{
int numBanque;
int numCompte;
float slode; };
Déclaration de deux variable structurées de type compte :
struct compte cpt1, cpt2;

12/12/2024 81
Les types composés : structures

Double déclaration d’une structure


struct compte{
int numBanque;
int numCompte;
float solde;
} cpt1, cpt2;
/* cpt1 occupera (sizeof) 12 octets en mémoire. */

12/12/2024 82
Les types composés : Manipulation des structures
Syntaxe
[Link]

Manipulation
• Une variable structurée peut être manipulée :
• champ par champ (opérations de lecture et mise à jour, etc.),
• ou comme un tout (opérations de copie, initialisation, etc.)
• L’opérateur point permet de référencer le champ champ de la variable variable

Syntaxe
Dans une expression :
float s = [Link] + [Link] ;
Modification :
[Link] += 101.1;

12/12/2024 83
Les types composés : Manipulation des structures

Copie de structure
L’opérateur = peut être utilisé sur des variables structurées, Il permet de copier champ à
champ (ce n’était pas possible avec les tableaux !)

Syntaxe
newCpt = cpt1;
Est équivalent à :
[Link] = [Link];
[Link] = [Link];
[Link] = [Link] ;

12/12/2024 84
Les types composés : Manipulation des structures
Syntaxe d’initialisation à la déclaration de variable
struct nomStruct variable ={exp1, ..., expN} ;

Syntaxe d’initialisation par copie


struct nomStruct newVariable = oldVariable ;

Manipulation
• L’initialisation à la déclaration est possible (comme pour tableau),
• L’ordre des expressions (exp1, exp2, etc.) est le même que celui des champs,
• Les champs manquants sont initialisés à 0 ou NULL,
• On peut imbriquer les initialiseurs entre { et } (structures et/ou tableaux imbriqués)
• Exemple : struct compte cpt ={180, 1234, 1.1};

12/12/2024 85
Les types composés : Manipulation des structures

Question
Afficher une variable structurée de type compte.

Réponse
Il faut afficher les champs un par un, à la main ! Exemple :
printf("Compte\n");
printf("----\n");
printf("Banque : %i\n", [Link]);
printf("Numéro : %i\n", [Link]);
printf("Solde : %f\n", [Link]);

12/12/2024 86
Les types composés : Manipulation des structures

Structure et typedef
struct compte{
int numBanque;
int numCompte;
float slode;
};
typedef struct compte compteType;
Typedef int unnouveauint;
int main(){
compteType c;
unnouveauint i;
...
}

12/12/2024 87
Les types composés : Manipulation des structures
Réponse
#include <math.h>
Question
#include <stdio.h>
struct complexe{
Calculer et afficher la norme du nombre complexe 2 +3i en représentant le nombre
double reelle;
complexe par une structure C.
double imaginaire; };
typedef struct complexe complexe;
int main(){
complexe z = {2,3};
double norme = sqrt([Link] * [Link] + [Link]
*[Link]);
printf("norme de %.2f+%.2fi : %f", [Link],[Link],
norme);
/* resultat : 3.605551 * /
return 0;
}

12/12/2024 88
Les types composés : Structures et Tableaux
Tableaux dans structure
struct id{
char nom[50];
char prenom[50];
int dateNaissance[3];
};

Remarques
• Des champs tableaux peuvent être dans une structure,
• Exemple d’initialisation : (imbrication des initialiseurs)
struct id
id1={"SADIQ","Abderrahmane",{1,1,2019}};
• Accéder à un élément de la même façon : (mois de naissance)
[Link][1];
• Une variable de type struct id occupe 112 octets.

12/12/2024 89
Les types composés : Structures et Tableaux
Tableaux dans structure
id2 = id1;
/* est equivalent à */
[Link][0] = [Link][0];
...
[Link][49] = [Link][49];
[Link][0] = [Link][0];
...
[Link][49] = [Link][49];
[Link][0] = [Link][0];
[Link][1] = [Link][1];
[Link][2] = [Link][2];

Remarques
• L’affectation (=) et l’initialisation copient récursivement les champs.

12/12/2024 90
Les types composés : Structures et Tableaux
Structures et tableaux
struct id{
char nom[TAILLE];
char prenom[TAILLE];
int dateNaissance[3]; /
};
struct id groupe[MAX];

Questions
• Comment accéder au j-ème caractère du prénom du i-ème membre du groupe ?
• Comment modifier le jour de naissance du i-ème membre du groupe ?

Réponse
• accès au j-ème caractère du prénom du i-ème membre du groupe :
groupe[i].prenom[j];
• modifier le jour de naissance du i-ème membre du groupe :
12/12/2024 groupe[i].dateNAissance[0] = jour; 91
Les types composés : Structures

Présentation en mémoire ?
Exemple:
struct ma_struct
{ char a;
short b;
};
struct ma_struct tab[7]

12/12/2024 92
Structure en Paramètres
Utilisation

• Une variable de type structure peut bien entendu être utilisée comme
paramètre d’une fonction.
• Le passage se déroule alors comme pour une variable de type simple : on doit
choisir entre un passage par valeur ou par adresse.
• Supposons qu’on a une fonction recevant en paramètre l’adresse d’une
variable de type : struct personne
void ma_fonction(struct personne* x);

• Alors la modification d’un de ses champs passe par l’utilisation de l’opérateur


*.
• Par exemple, si on veut changer l’âge de la personne x, on utilisera
l’expression : (*x).age = 99;

12/12/2024 93
Structure en Paramètres
Utilisation

• Notez bien l’utilisation des parenthèses. En effet, on veut appliquer


l’opérateur * seulement à l’expression x, qui est de type struct personne*.
• On obtient alors l’expression *x, qui est de type struct personne.
• On peut alors appliquer l’opérateur . à cette expression *x, afin d’obtenir son
champ age.
• Il serait impossible d’appliquer directement l’opérateur . à x, car cet opérateur
ne s’applique qu’à une structure. Or, x n’est pas une structure, mais l’adresse
d’une structure.
• Cependant, un opérateur spécial peut être utilisé pour accéder à un champ à
partir de l’adresse d’une structure. Il s’agit de l’opérateur ->, qu’on utilise de
la façon suivante :
x->age = 99;

12/12/2024 94
Exercice
La FPT organise un tournoi de tennis de table en double. Chaque équipe
désirant participer se compose 2 joueurs et possède un nom. Chaque joueur
est caractérisé par un nom, un prénom, un âge et un score allant de 0 à 100
indiquant son niveau.
1. Définissez les types structures joueur et equipe correspondants.
2. Écrivez une fonction saisis_joueur permettant de saisir les caractéristiques
d’un joueur. Le paramètre doit être passé par adresse.
3. En utilisant la fonction précédente, écrivez une fonction saisis_equipe
permettant de saisir les caractéristiques d’une équipe. Le paramètre doit
être passé par adresse.
4. Écrivez une fonction main qui crée et remplit un tableau de N équipes en
utilisant la fonction saisis_équipe.
5. Écrivez des fonctions affiche_joueur et affiche_equipe pour afficher à
l’écran les équipes et leurs joueurs.
6. Complétez la fonction main précédente de manière à afficher les équipes
après la saisie.
12/12/2024 95
Les types composés : Unions
Syntaxe
union nomUnion {
type1 champ1;
...
typeN champN;
};

Définition
• Une union est composée de champs : nommés et typés,
• Elle désigne un ensemble de variables de types différents susceptibles d’occuper
alternativement une même zone mémoire,
• Elle permet de définir une variable pouvant être d’un type au choix parmi un ensemble
fini de types.

12/12/2024 96
Les types composés : Unions
Syntaxe
union nomUnion {
type1 champ1;
...
typeN champN;
};

A noter…
• On ne peut utiliser qu’un champ à la fois : les champs partagent le même
emplacement en mémoire,
• La place réservée (octets) en mémoire pour la représenter correspond à
la taille du champ le plus grand.

12/12/2024 97
Les types composés : Unions
Exemple 1
union jour {
char lettre;
int numero;
};

Exemple 2
union nombre {
int entier;
double flottant;
};

A noter…
• Occupation en mémoire de jour : 4 octets,
• Occupation en mémoire de nombre : 8 octets.

12/12/2024 98
Les types composés : Unions
Présentation en mémoire ?
Exemple:
union taille
{ short centimetres;
float metres;
};
union taille t;

12/12/2024 99
Les types composés : Manipulation des Unions
Exemple
union nombre nbr;
union jour hier, demain;
[Link] = 100;
[Link] *= 3;
[Link] = ’V’;
printf("hier = %c\n",[Link]);
[Link] = 4;
[Link] = ([Link] + 2)%7;
printf("demain = %d\n",[Link]);

Déclaration et utilisation
• Les unions se déclarent et s’utilisent comme les structures,
• la variable hier de type union jour peut être soit un entier soit un caractère.

12/12/2024 100
Les types composés : Unions
Exemple (bout de code)
union nombre nbr;
double x;
[Link] = 100; //ok
[Link] = 102; //ok
x=[Link]; // non

A noter…
Il ne faut pas écrire dans un champ puis lire depuis un autre : il faut se
souvenir du champ actif !

12/12/2024 101
Les types composés : Unions
Solution
typedef union {
int ent;
double flot;
} valeur;
typedef struct {
int type;
valeur val;
} nombre;
nombre nbr={0, 100};

Utiliser discriminant pour se souvenir du champ actif


• le champ entier type dans struct nombre sert de discriminant :
• si [Link]==0, alors on utilise [Link]
• si [Link]==1, alors on utilise [Link]

12/12/2024 102
Les types composés : Énumérations
Syntaxe
enum modele{constante0, constante1, ..., constanteN};

Définition
• Une énumération permet de définir un type par la liste des valeurs qu’il peut
prendre,
• Elle est définie par le mot-clef enum et un identificateur de modèle, suivis de
la liste des valeurs possible que peut prendre une variable de ce type,
• En réalité, les constantes sont représentées comme des int : les valeurs
possibles constante0, constante1,...,constanteN sont codées par des entiers
de 0 à N.

12/12/2024 103
Les types composés : Énumérations
Exemple
enum booleen {faux, vrai};
enum couleur{jaune, rouge, bleu, vert};
enum booleen b;
enum couleur c;
b = vrai; c=bleu;
printf("b = %d, c=%d\n",b,c);

Définition
• Le type enum booléen associe l’entier 0 à la valeur faux et l’entier 1 à la valeur
vrai,
• On peut modifier le codage par défaut des valeurs de la liste lors de la
déclaration du type énuméré. Exemple :
enum couleur {jaune=12, rouge=23, bleu=33 , vert=40};

12/12/2024 104
Exercice

Une entreprise a besoin de stocker dans un tableau le nombre


d’heures travaillées par jours pendant une semaine.
• Définissez un type énuméré semaine pour représenter les 7
jours de la semaine.
• Écrivez une fonction afficher_semaine permettant d’afficher
le mot (nom du jour) correspondant au numéro du jours
passé en paramètre.
• Écrivez une fonction saisir_nbHeures demandant à un
utilisateur de remplir le tableau d’heures mensuelles.

12/12/2024 105
Les types composés : Nommage de types
Syntaxe
typedef type nom_du_type;

Explication
• Il est possible de définir un nouvel identificateur pour un type, en utilisant
l’instruction typedef.

• Si le type est anonyme, alors il le fait de le nommer le rend plus facile à


manipuler. S’il a déjà un nom, alors ce nouveau nom ne supprime pas l’ancien.

• La principale utilisation de typdef concerne les types structurés, unions et


énumérés, car elle évite de devoir répéter les mots clés struct, union ou enum
en permanence.

12/12/2024 108
Les types composés : Nommage de types
Exemple
struct s_joueur
{ char prenom[10];
char nom[10];
short age;
short niveau;
};
typedef struct s_joueur joueur;

Explication
• Ici, on déclare d’abord un type structure, dont le nom complet est struct s_joueur.
• On définit ensuite un nouveau « joueur » pour ce type en utilisant typedef.
• Par la suite, on peut donc utiliser n’importe lequel de ces deux noms, qui font
référence au même type : soit struct s_joueur, soit joueur.
• Pour déclarer une nouvelle variable x de ce type, on peut donc écrire : joueur x;
• Mais on peut aussi continuer à faire : struct s_joueur x;
12/12/2024 109
Les types composés : Nommage de types
A noter…
Il est possible de définir le type que l’on veut nommer directement dans
l’instruction typedef, de la façon suivante :
typedef struct s_joueur
{ char prenom[10];
char nom[10];
short age;
short niveau;
} joueur;
Ou encore
typedef struct
{ char prenom[10]; char nom[10];
short age;
short niveau;
} joueur;

12/12/2024 110
LES POINTEURS
Les pointeurs

Rappel
• Toute variable manipulée dans un programme est stockée quelque part en
mémoire centrale,

• La mémoire est constituée d’octets qui sont identifiés de manière univoque


par un numéro qu’on appelle adresse,

• Donc : pour retrouver/manipuler une variable, il suffit donc de connaître


l’adresse de l’octet où elle est stockée,

• Ou aussi : pour retrouver/manipuler une variable qui recouvre plusieurs


octets contigus, il faut l’adresse du premier de ces octets.

12/12/2024 112
Les Pointeurs
Imaginez…

Si on manipule directement les adresses des variables dans un programme

12/12/2024 113
Les Pointeurs

La solution est déjà là…


• On désigne les variables par des identificateurs et non pas par leur adresse
mémoire,
• Le compilateur fait le lien entre l’identificateur d’une variable et son adresse
en mémoire.

À noter que…
il est parfois très pratique de manipuler directement une variable par
son adresse.

Définition: Lvalue (left value)


• Lvalue = tout objet pouvant être placé à gauche d’un opérateur d’affectation,
• Une Lvalue est caractéerisée par :
• son adresse mémoire à partir de laquelle l’objet est stocké,
• sa valeur qui est stocké à cette adresse.
12/12/2024 114
Les Pointeurs
Exemple
int a,b;
a=6;
b=a;

Imaginez…

Explication
Deux variables différentes ont des adresses différentes,
L’affectation b = a; n’opère que sur les valeurs des variables,
Chaque variable est stockée sur 4 octets (int) : la valeur de a est stockée sur les
octets d’adresse 2293572 à 2293575
12/12/2024 115
Les Pointeurs

Adresse d’une variable


• L’opérateur & permet d’accéder à l’adresse d’une variable
• &i n’est pas une Lvalue, c’est une constante,
• On ne peut pas avoir &i à gauche d’un opérateur d’affectation.

Question
Comment peut-on manipuler les adresses alors ?

Réponse
• Il faut recourir à un nouveau type de variable : les pointeurs.

12/12/2024 116
Les Pointeurs

Syntaxe
Type *nomDuPointeur;

Adresse d’une variable


• Un pointeur est un objet Lvalue dont la valeur est égale à l’adresse d’un
autre objet de type type,
• type est le type de l’objet pointé,
• C’est une déclaration de nomDuPointeur associé à un objet,
• L’identificateur nomDuPointeur est donc un identificateur d’adresse : comme
étant un Lvalue, sa valeur est modifiable.

Exemple
int n=9; Int *p;
p=&n;
12/12/2024 117
Les Pointeurs
Exemple
Int *p; int n=9;
p=&n;

En mémoire

A noter…
La valeur d’un pointeur est toujours un entier : éventuellement un entier long,
Le type d’un pointeur dépend du type de l’objet vers lequel il pointe : *int, *char,
*float ou d’autres . . .

12/12/2024 118
Les Pointeurs
Question
• Si la valeur d’un pointeur est toujours un entier, donc pourquoi avoir des pointeurs typés ?
• C.à.d : pourquoi il faut à chaque fois donner le type de l’objet vers lequel il pointe ?
int *i; char *c; Float *f;

Réponse
• Le type d’un pointeur dépend du type de l’objet vers lequel il pointe puisque :
• à l’interprétation de la valeur d’un pointeur, il faut s’assurer du nombre des octets
pointés,
• lors de la manipulation de la valeur pointée, il faut préciser le type de la zone
pointée, et puis les valeurs stockées.

Exemple
• Un pointeur sur un objet de type char : la valeur du pointeur donne l’adresse de l’octet
ou l’objet est effectivement stocké,
• un pointeur sur un objet de type int : la valeur du pointeur donne seulement l’adresse
du premier octet des 4 octets où l’objet est stocké.
12/12/2024 119
Les Pointeurs

L’opérateur unaire d’indirection *


• Il permet d’accéder directement à la valeur de l’objet pointé
• Exemple : si p est un pointeur vers un entier a, *p désigne la valeur
de a : a est *p sont identiques (même adresse et valeur).

Exemple
int a=6; int *p;
p=&a;
printf("Valeur de la variable pointée par p est : %d\n", *p);
printf("Valeur de la variable a est : %d\n",a);

Résultats
Valeur de la variable pointée par p est : 6
Valeur de la variable a est : 6

12/12/2024 120
Les Pointeurs

Les pointeurs en C :
• & : obtenir l’adresse d’une variable existante,
• * : accéder au contenu stocké à une adresse valide,
• = : passer des adresses en argument, les retourner, les copier,
• effectuer des opérations limitées sur les adresses.

Exemple
int i, t[5]; float f;
int *p;
&i /* adresse de i */
&(t[1]) et &t[1] /*adresse de t[1] */
&(t+1) et &(i+1) */ invalides */
p = &i; /* p pointe sur i */
p = &f; /* non défini */
p =&(i+1); /* erreur de syntaxe */
12/12/2024 121
Les Pointeurs

Exemple (bout de code): Manipulation de p et *p


int main(){
int a = 10, b = 60;
int *p1, *p2;
p1 = &a;
p2 = &b;
*p1 = *p2;
}

En mémoire: avant et après l’affectation

12/12/2024 122
Les Pointeurs
En détails…
main()
{ int i = 3;
int *p;
p = &i;
printf("*p = %d \n",*p);
}
imprime *p = 3.
Dans ce programme, les objets i et *p sont identiques : ils ont mêmes adresse et valeur.
Nous sommes dans la configuration :

Cela signifie en particulier que toute modification de *p modifie i.

12/12/2024 123
Les Pointeurs
En détails…
main() main()
{ {
int i = 3, j = 6; int i = 3, j = 6;
int *p1, *p2; int *p1, *p2;
p1 = &i; p1 = &i;
p2 = &j; p2 = &j;
*p1 = *p2; p1 = p2;
} }
Avant la dernière affectation de chacun de ces programmes, on est dans une
configuration du type :

12/12/2024 124
Les Pointeurs
En détails…

Après l’affectation *p1 = *p2; du premier


programme, on a:

Par contre, l’affectation p1 = p2 du second


programme, conduit à la situation:

12/12/2024 125

Vous aimerez peut-être aussi