struct
- Possibilité d'agréger les informations au sein de variables conteneurs
- Intérêt
- Modélisation de l'information stockée dans les applications informatiques mimant la façon avec laquelle elle existe concrètement : de façon structurée
- Manipulation de plusieurs informations en une seule information
- Amélioration de l'expréssivité du code
- Utilisation de noms de types expressifs
- Explicitation du lien existant entre certaines variables par référence à la variable qui les "contient"
- Simplification du code
- ...
- Déclaration d'une variable selon un type struct
struct nomStruct nomVariable;
Valeurs des champs aléatoires
struct nomStruct nomVariable = { v1,v2,...,vN };
Valeurs des champs initialisées avec les valeurs données entre accolades (dans l'ordre et sous réserve que les types correspondent)
- Déclaration d'une variable pointeur sur un type struct
struct nomStruct* nomVariable;
- Déclaration d'une variable pointeur sur pointeur sur un type struct
struct nomStruct** nomVariable;
- Accès aux champs d'une variable nomVariable de type struct
nomVariable.nomChamp
- Accès aux champs d'une variable nomVariable de type pointeur sur struct
(*nomVariable).nomChamp
ou plus lisiblement
nomVariable->nomChamp
- Opérateurs
- = : affectation champ pour champ
- sizeof : nombre d'octets d'une variable déclarée selon un type struct
- & : adresse d'une variable déclarée selon un type struct
- * : valeur d'une variable déclarée de type pointeur sur type struct
- Exemples
#include <stdio.h>
struct date {
int jour;
int mois;
int annee;
};
void main(void) {
struct date d;
d.jour = 2;
d.mois = 8;
d.annee = 1993;
printf("%02d:%02d:%d\n", d.jour, d.mois, d.annee);
}
|
Struct1.c - Struct1.exe
|
|
#include <stdio.h>
struct date {
int jour;
int mois;
int annee;
};
void main(void) {
struct date d1;
struct date d2 = { 2, 8,1993 };
struct date d3 = { 11,10,2001 };
struct date d4 = { 0, 0, 0 };
struct date* d;
d1.jour = 2;
d1.mois = 8;
d1.annee = 1993;
printf("d1 : %02d:%02d:%4d %p\n", d1.jour, d1.mois, d1.annee,&d1);
printf("d2 : %02d:%02d:%4d %p\n", d2.jour, d2.mois, d3.annee,&d2);
printf("d3 : %02d:%02d:%4d %p\n", d3.jour, d3.mois, d3.annee,&d3);
printf("\n");
printf("d4 : %02d:%02d:%4d %p\n", d4.jour, d4.mois, d4.annee,&d4);
d4 = d1;
printf("d4 : %02d:%02d:%4d %p\n", d4.jour, d4.mois, d4.annee,&d4);
printf("\n");
printf("%zu\n", sizeof(struct date));
printf("%p\n", &d1);
printf("%p\n", &d1.jour);
printf("%p\n", &d1.mois);
printf("%p\n", &d1.annee);
printf("\n");
d = &d3;
printf("*d : %02d:%02d:%4d %p\n", (*d).jour, (*d).mois, (*d).annee, d);
printf("*d : %02d:%02d:%4d %p\n", d->jour, d->mois, d->annee, d);
}
|
Struct2.c - Struct2.exe
|
d1 : 02:08:1993 000000045E0FF9F0
d2 : 02:08:2001 000000045E0FFA10
d3 : 11:10:2001 000000045E0FF9E0
d4 : 00:00: 0 000000045E0FFA00
d4 : 02:08:1993 000000045E0FFA00
12
000000045E0FF9F0
000000045E0FF9F0
000000045E0FF9F4
000000045E0FF9F8
*d : 11:10:2001 000000045E0FF9E0
*d : 11:10:2001 000000045E0FF9E0
|
|
- Fonctions et struct
- Compatibilité des types struct avec la programmation de fonctions
- Utilisation comme n'importe quel type primitif
- Exemples
#include <stdio.h>
#include <stdbool.h>
struct horaire {
int heure;
int minute;
int seconde;
};
void afficherHoraire(struct horaire h) {
printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
}
int calculerSecondes(struct horaire h) {
return h.heure * 3600 + h.minute * 60 + h.seconde;
}
int comparerHoraires(struct horaire h1, struct horaire h2) {
int m1 = calculerSecondes(h1);
int m2 = calculerSecondes(h2);
if (m1 > m2) {
return 1;
}
if (m1 < m2) {
return -1;
}
return 0;
}
void ajouterUneSeconde(struct horaire* h) {
h->seconde++;
if (h->seconde == 60) {
h->seconde = 0;
h->minute++;
if (h->minute == 60) {
h->minute = 0;
h->heure++;
if (h->heure == 24) {
h->heure = 0;
}
}
}
}
void main(void) {
struct horaire h1 = { 12, 59,59 };
struct horaire h2 = { 23, 59,59 };
afficherHoraire(h1);
printf(" = %d secondes\n", calculerSecondes(h1));
afficherHoraire(h2);
printf(" = %d secondes\n", calculerSecondes(h2));
printf("\n");
printf("%d\n", comparerHoraires(h1, h1));
printf("%d\n", comparerHoraires(h1, h2));
printf("%d\n", comparerHoraires(h2, h1));
printf("\n");
ajouterUneSeconde(&h1);
afficherHoraire(h1);
printf("\n");
ajouterUneSeconde(&h2);
afficherHoraire(h2);
printf("\n");
}
|
StructsEtFonctions1.c - StructsEtFonctions1.exe
|
12:59:59 = 46799 secondes
23:59:59 = 86399 secondes
0
-1
1
13:00:00
00:00:00
|
|
#include <stdio.h>
struct horaire {
int heure;
int minute;
int seconde;
};
void afficherHoraire(struct horaire h) {
printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
}
int calculerSecondes(struct horaire h) {
return h.heure * 3600 + h.minute * 60 + h.seconde;
}
struct horaire calculerHoraire(int secondes) {
struct horaire h = { secondes / 3600,(secondes / 60) % 60,secondes % 60 };
return h;
}
struct horaire calculerHoraireSecondeSuivante(struct horaire h) {
struct horaire nh = h;
nh.seconde++;
if (nh.seconde == 60) {
nh.seconde = 0;
nh.minute++;
if (nh.minute == 60) {
nh.minute = 0;
nh.heure++;
if (nh.heure == 24) {
nh.heure = 0;
}
}
}
return nh;
}
void main(void) {
int s = 53227;
struct horaire h = calculerHoraire(s);
printf("%d secondes = ", s);
afficherHoraire(h);
printf("\n");
struct horaire h2 = calculerHoraireSecondeSuivante(h);
afficherHoraire(h2);
printf("\n");
h2 = calculerHoraireSecondeSuivante(h2);
afficherHoraire(h2);
printf("\n");
}
|
StructsEtFonctions2.c - StructsEtFonctions2.exe
|
53227 secondes = 14:47:07
14:47:08
14:47:09
|
|
- Tableaux de type élémentaire de type struct
- Pas de problème particulier en allocation statique comme en allocation dynamique
- Exemple
#include <stdio.h>
#include <stdlib.h>
struct horaire {
int heure;
int minute;
int seconde;
};
void afficherHoraire(struct horaire h) {
printf("%02d:%02d:%02d", h.heure, h.minute, h.seconde);
}
void afficherTableauHoraires(struct horaire* th, int taille) {
for (int i = 0; i < taille; i++) {
afficherHoraire(th[i]);
printf("\n");
}
}
void afficherTableauPointeursHoraire(struct horaire** th, int taille) {
for (int i = 0; i < taille; i++) {
afficherHoraire(*th[i]);
printf("\n");
}
}
struct horaire tirerAuSortHoraire(void) {
struct horaire h = { rand() % 24,rand() % 60,rand() % 60 };
return h;
}
struct horaire* creerTableauHorairesTiresAuSort(int taille) {
struct horaire* th = (struct horaire*) calloc(taille, sizeof(struct horaire));
if (th != NULL) {
for (int i = 0; i < taille; i++) {
th[i] = tirerAuSortHoraire();
}
}
return th;
}
struct horaire** creerTableauHoraires(int taille) {
struct horaire** th = (struct horaire**) calloc(taille, sizeof(struct horaire*));
if (th != NULL) {
int i = 0;
while ((i < taille) &&
((th[i] = (struct horaire*) calloc(1, sizeof(struct horaire))) != NULL)) {
i++;
}
if (th[taille - 1] == NULL) {
for (int j = 0; j < i; j++) {
free(th[j]);
th[j] = NULL;
}
}
}
return th;
}
void libererTableauHoraires(struct horaire** th, int taille) {
if (th != NULL) {
for (int i = 0; i < taille; i++) {
free(th[i]);
th[i] = NULL;
}
free(th);
th = NULL;
}
}
#define TAILLE_1 5
void tester1(void) {
const int seed = 6;
srand(seed);
struct horaire th[TAILLE_1];
printf("%d %zu %zu\n", TAILLE_1, sizeof(struct horaire), sizeof(th));
for (int i = 0; i < TAILLE_1; i++) {
th[i] = tirerAuSortHoraire();
}
afficherTableauHoraires(th, TAILLE_1);
printf("\n");
}
#undef TAILLE_1
void tester2(int taille) {
const int seed = 6;
srand(seed);
struct horaire* th = (struct horaire*) calloc(taille, sizeof(struct horaire));
printf("%d %zu %zu\n",taille, sizeof(struct horaire*), sizeof(th));
if (th != NULL) {
afficherTableauHoraires(th, taille);
printf("\n");
for (int i = 0; i < taille; i++) {
th[i] = tirerAuSortHoraire();
}
afficherTableauHoraires(th, taille);
free(th);
th = NULL;
}
printf("\n");
}
void tester3(int taille) {
const int seed = 6;
srand(seed);
struct horaire* th = creerTableauHorairesTiresAuSort(taille);
printf("%d %zu %zu\n", taille, sizeof(struct horaire*), sizeof(th));
if (th != NULL) {
afficherTableauHoraires(th, taille);
free(th);
th = NULL;
}
printf("\n");
}
void tester4(int taille) {
const int seed = 6;
srand(seed);
struct horaire** th = creerTableauHoraires(taille);
printf("%d %zu %zu\n", taille, sizeof(struct horaire**), sizeof(th));
if (th != NULL) {
afficherTableauPointeursHoraire(th, taille);
libererTableauHoraires(th, taille);
th = NULL;
}
printf("\n");
}
void main(void) {
tester1();
tester2(3);
tester3(4);
tester4(5);
}
|
TableauxDeStruct.c - TableauxDeStruct.exe
|
5 12 60
10:13:59
01:46:09
16:22:56
20:46:45
00:55:58
3 8 8
00:00:00
00:00:00
00:00:00
10:13:59
01:46:09
16:22:56
4 8 8
10:13:59
01:46:09
16:22:56
20:46:45
5 8 8
00:00:00
00:00:00
00:00:00
00:00:00
00:00:00
|
|
- Type struct avec champ(s) de type tableau
- Pas de problème particulier en allocation statique comme en allocation dynamique pour les champs
- Exemple
#include <stdio.h>
#include <stdlib.h>
struct clefStatique {
char encode[128];
char decode[128];
};
struct clefDynamique {
char* encode;
char* decode;
};
void initialiserTableauEncodage(char* encode, int delta) {
for (int i = 0; i < 128; i++) {
encode[i] = (i + delta + 128) % 128;
}
}
void initialiserTableauDecodage(char* decode, char* encode) {
for (int i = 0; i < 128; i++) {
decode[encode[i]] = (char) i;
}
}
struct clefStatique creerClefStatique(int delta) {
struct clefStatique cs;
initialiserTableauEncodage(cs.encode, delta);
initialiserTableauDecodage(cs.decode, cs.encode);
return cs;
}
struct clefDynamique creerClefDynamique(int delta) {
struct clefDynamique cd;
cd.encode = (char*) calloc(128, sizeof(char));
if (cd.encode != NULL) {
initialiserTableauEncodage(cd.encode, delta);
}
cd.decode = (char*) calloc(128, sizeof(char));
if (cd.decode != NULL) {
initialiserTableauDecodage(cd.decode, cd.encode);
}
return cd;
}
void libererClefDynamique(struct clefDynamique cd) {
if (cd.encode != NULL) {
free(cd.encode);
cd.encode = NULL;
}
if (cd.decode != NULL) {
free(cd.decode);
cd.decode = NULL;
}
}
void main(void) {
printf("Taille d'une clef statique : %zu octets\n", sizeof(struct clefStatique));
printf("Taille d'une clef dynamique : %zu octets\n", sizeof(struct clefDynamique));
printf("\n");
struct clefStatique cs = creerClefStatique(4);
struct clefDynamique cd = creerClefDynamique(-6);
printf("Taille de la clef cs : %zu octets\n", sizeof(cs));
printf("Taille de la clef cd : %zu octets\n", sizeof(cd));
printf("\n");
char c1 = 'A';
char ec1 = cs.encode[c1];
char dec1 = cs.decode[ec1];
printf("%c %c %c\n", c1, ec1, dec1);
char c2 = 's';
char ec2 = cd.encode[c2];
char dec2 = cd.decode[ec2];
printf("%c %c %c\n", c2, ec2, dec2);
libererClefDynamique(cd);
printf("\n");
}
|
StructsDeTableaux.c - StructsDeTableaux.exe
|
Taille d'une clef statique : 256 octets
Taille d'une clef dynamique : 16 octets
Taille de la variable cs : 256 octets
Taille de la variable cd : 16 octets
|
|
- Type struct avec champ de type struct
- Possible dans la mesure où aucun cycle de struct non pointeur n'est créé (type struct A possèdant un champ de type struct A directement ou indirectement)
- Exemple
#include <stdio.h>
#include <math.h>
struct position {
double x;
double y;
};
struct segment {
struct position pi;
struct position pf;
};
struct triplet {
struct segment s1;
struct segment s2;
struct segment s3;
};
double calculerLongueurSegment(struct segment s) {
return sqrt(pow(s.pi.x - s.pf.x, 2.0) + pow(s.pi.y - s.pf.y, 2.0));
}
double calculerLongueurMaxSegments(struct triplet trp) {
double l1 = calculerLongueurSegment(trp.s1);
double l2 = calculerLongueurSegment(trp.s2);
double l3 = calculerLongueurSegment(trp.s3);
if ((l1 >= l2) && (l1 >= l3)) {
return l1;
}
if (l2 >= l3) {
return l2;
}
return l3;
}
void main(void) {
printf("%zu %zu %zu\n", sizeof(struct triplet),
sizeof(struct segment),
sizeof(struct position));
struct triplet trp = { { { 1.2, 3.4 },{ -2.3, 4.6 } },
{ { 4.5,-5.6 },{ 7.2, 1.4 } },
{ { -5.3, 0.0 },{ -1.3, 8.9 } } };
printf("%zu %zu %zu\n", sizeof(trp), sizeof(trp.s2), sizeof(trp.s2.pi));
printf("\n");
printf("Longueur maximale des segments : %lf\n", calculerLongueurMaxSegments(trp));
}
|
StructsDeStructs.c - StructsDeStructs.exe
|
96 32 16
96 32 16
Longueur maximale des segments : 9.757561
|
|
- Type struct avec champ de type pointeur sur type struct
- Pas de problème particulier même avec cycle
- Exemple
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
struct sommet {
double x;
double y;
};
struct polygone {
int ns;
struct sommet* ts;
};
void afficherSommet(struct sommet s) {
printf("%6.2lf%6.2lf", s.x, s.y);
}
double calculerDistanceSommets(struct sommet s1, struct sommet s2) {
return sqrt(pow(s1.x - s2.x, 2.0) + pow(s1.y - s2.y, 2.0));
}
struct sommet creerSommet() {
struct sommet s;
s.x = (rand() % 101) / 100.0;
s.y = (rand() % 101) / 100.0;
return s;
}
double calculerPerimetrePolygone(struct polygone p) {
double l = 0.0;
for (int i = 0; i < p.ns - 1; i++) {
l += calculerDistanceSommets(p.ts[i], p.ts[i + 1]);
}
l+= calculerDistanceSommets(p.ts[p.ns - 1], p.ts[0]);
return l;
}
void afficherPolygone(struct polygone p) {
printf("%d sommets\n", p.ns);
for (int i = 0; i < p.ns; i++) {
afficherSommet(p.ts[i]);
printf("\n");
}
}
struct polygone creerPolygone(int n) {
struct polygone p;
p.ts = (struct sommet*) calloc(n, sizeof(struct sommet));
if (p.ts == NULL) {
p.ns = 0;
}
else {
p.ns = n;
for (int i = 0; i < n; i++) {
p.ts[i] = creerSommet();
}
}
return p;
}
void detruirePolygone(struct polygone pl) {
if (pl.ts != NULL) {
free(pl.ts);
pl.ts = NULL;
}
}
void main(void) {
srand(2);
printf("%zu %zu\n", sizeof(struct polygone), sizeof(struct sommet));
struct polygone pl = creerPolygone(5);
printf("%zu\n", sizeof(pl));
printf("\n");
afficherPolygone(pl);
printf("Perimetre : %lf\n", calculerPerimetrePolygone(pl));
detruirePolygone(pl);
}
|
StructsDePointeursSurStructs.c - StructsDePointeursSurStructs.exe
|
16 16
16
5 sommets
0.45 0.27
0.59 0.19
0.93 0.56
0.46 0.70
1.00 0.35
Perimetre : 2.353441
|
|
|
enum
- Possibilité de déclarer des énumérations de constantes entières
- Possibilité de créer des énumérations possèdant un nom de type
- Possibilité de créer un type correspondant à une énumération en utilisant le typedef
|