pdf - e-book - archive - github.com

1.9  Structures

1.9.1  Définition

Nous avons utilisé des tableaux pour désigner, avec un nom unique, un ensemble de variables. Par exemple, un tableau T à n éléments est un ensemble n de variables désignées par la lettre T. Dans un tableau, les variables doivent être de type homogène, cela signifiant qu’il n’est pas possible de juxtaposer des char et des int dans un tableau. Lorsque l’on souhaite faire cohabiter dans une variable non scalaire des types hétérogènes, on utilise des structures.

Une structure, appelé enregistrement dans d’autres langages, est une variable contenant plusieurs variables, appelées champs. Si une structure t contient un char et un int, chacun de ces champs portera un nom, par exemple i et c. Dans ce cas, t.c désignera le char de t et t.i l’int de t.

1.9.2  Déclaration

Pour créer un type structuré, on utilise la syntaxe suivante :

struct nomdutype
{
 typechamp_1 nomchamp_1; 
 typechamp_2 nomchamp_2; 
 ...
 typechamp_n nomchamp_n;
};

On précise donc le nom de ce type structuré, et entre les accolades, la liste des champs avec pour chacun d’eux son type. Vous remarquez que le nombre de champs est fixé d’avance. On n’accède pas à un champ avec un indice mais avec un nom. Considérons par exemple le type structuré suivant :

struct point
{
  double abs;
  double ord;
};

Ce type permet de représenter un point dans R2, avec respectivement uns abscisse et une ordonnée. struct point est maintenant un type, il devient possible de déclarer un point p comme tout autre variable :

struct point p;

1.9.3  Accès aux champs

On accède aux champs d’une variable structurée à l’aide de la notation pointée

nomvariable.nomduchamp

Ainsi, le champ ord de notre variable p sera accessible avec p.ord et le champ abs de notre variable p sera accessible avec p.abs. Voici un exemple de programme illustrant ce principe :

#include<stdio.h>

struct point
{
  double abs;
  double ord;
};


main()
{
  struct point p;
  p.ord = 2;
  p.abs = p.ord + 1;
  printf("p = (%f, %f)\n", p.abs, p.ord);
}

Télécharger le fichier

Ce programme affiche :

p = (3.000000, 2.000000)

Attention, l’opérateur d’accès au champ . est prioritaire sur tous les autres opérateurs unaires, binaires et ternaires ! Il faudra vous en rappeler quand on étudiera les listes chaînées.

1.9.4   Typedef

On se débarasse du mot clé struct en renommant le type, on utilisera par exemple la syntaxe suivante :

#include<stdio.h>

typedef struct point
{
  double abs;
  double ord;
}point;


main()
{
  point p;
  p.ord = 2;
  p.abs = p.ord + 1;
  printf("p = (%f, %f)\n", p.abs, p.ord);
}

Télécharger le fichier

point est donc le nom de ce type structuré.

1.9.5  Tableaux de structures

Rien de nous empêche de créer des tableaux de structures, par exemple :

#include<stdio.h>

#define N 10

typedef struct point
{
  double abs;
  double ord;
}point;


main()
{
  point p[N];
  int i;
  p[0].ord = 0;
  p[0].abs = 1;
  for(i = 1 ; i < N ; i++)
    {
      p[i].ord = p[i - 1].ord + 1.;
      p[i].abs = p[i - 1].abs + 2.;
    }
  for(i = 0 ; i < N ; i++)
    {
      printf("p[%d] = (%f, %f)\n", i, p[i].abs, p[i].ord);
    }  
}

Télécharger le fichier

Ce programme affiche :

p[0] = (1.000000, 0.000000)
p[1] = (3.000000, 1.000000)
p[2] = (5.000000, 2.000000)
p[3] = (7.000000, 3.000000)
p[4] = (9.000000, 4.000000)
p[5] = (11.000000, 5.000000)
p[6] = (13.000000, 6.000000)
p[7] = (15.000000, 7.000000)
p[8] = (17.000000, 8.000000)
p[9] = (19.000000, 9.000000)

1.9.6  Structures et fonctions

Lorsqu’on les passe en paramètre, les structures se comportent comme des variables scalaires, cela signifie qu’on ne peut les passer en paramètre que par valeur. Par contre, un tableau de structures est nécessairement passé en paramètre par référence. Réecrivons le programme précédent avec des sous-programmes :

#include<stdio.h>

#define N 10

typedef struct point
{
  double abs;
  double ord;
}point;

void initTableauPoints(point p[], int n)
{
  int i;
  p[0].ord = 0;
  p[0].abs = 1;
  for(i = 1 ; i < n ; i++)
    {
      p[i].ord = p[i - 1].ord + 1.;
      p[i].abs = p[i - 1].abs + 2.;
    }  
}

void affichePoint(point p)
{
  printf("(%f, %f)", p.abs, p.ord);
}

void afficheTableauPoints(point p[], int n)
{
  int i;
 for(i = 0 ; i < n ; i++)
    {
      printf("p[%d] = ", i);
      affichePoint(p[i]);
      printf("\n");
    }  
}

main()
{
  point p[N];
  initTableauPoints(p, N);
  afficheTableauPoints(p, N);  
}

Télécharger le fichier

Comme une structure se comporte comme une variable scalaire, il est possible de retourner une structure dans une fonction, il est donc possible de modifier le programme ci-avant de la sorte :

#include<stdio.h>

#define N 10

typedef struct point
{
  double abs;
  double ord;
}point;

point nextPoint(point previous)
{
  point result;
  result.ord = previous.ord + 1.;
  result.abs = previous.abs + 2.;
  return result;
}

void initTableauPoints(point p[], int n)
{
  int i;
  p[0].ord = 0;
  p[0].abs = 1;
  for(i = 1 ; i < n ; i++)
    p[i] = nextPoint(p[i - 1]);
}

void affichePoint(point p)
{
  printf("(%f, %f)", p.abs, p.ord);
}

void afficheTableauPoints(point p[], int n)
{
  int i;
 for(i = 0 ; i < n ; i++)
    {
      printf("p[%d] = ", i);
      affichePoint(p[i]);
      printf("\n");
    }  
}

main()
{
  point p[N];
  initTableauPoints(p, N);
  afficheTableauPoints(p, N);  
}

Télécharger le fichier