Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. C++
  3. Structuration des données
Extrait - C++ Des fondamentaux du langage aux applications (4e édition)
Extraits du livre
C++ Des fondamentaux du langage aux applications (4e édition) Revenir à la page d'achat du livre

Structuration des données

Programmation structurée

Les langages de programmation ont commencé très tôt à assembler les instructions sous la forme de groupes réutilisables, les fonctions. Les variables ont naturellement pris le même chemin, bien qu’un peu plus tardivement.

Le tableau permet de traiter certains algorithmes, à condition que la donnée à traiter soit d’un type uniforme (char, int...). Lorsque la donnée à traiter contient des informations de natures différentes, il faut recourir à plusieurs tableaux, ou bien à un seul tableau en utilisant un type fourre-tout void*. Il faut bien le reconnaître, cette solution est à proscrire.

À la place, nous définissons des structures regroupant plusieurs variables appelées champs. Ces variables existent en autant d’exemplaires que souhaité, chaque exemplaire prenant le nom d’instance.

Le langage C++ connaît plusieurs formes composites :

  • Les structures et les unions, aménagées à partir du C.

  • Les classes, qui seront traitées au chapitre La programmation orientée objet.

1. Structures

Les structures du C++, comme celles du C, définissent de nouveaux types de données. Le nom donné à la structure engendre un type de données :

struct Personne  
{  
  char nom[50];  
  int age;  
} ; 

À partir de cette structure Personne, nous allons maintenant créer des variables, en suivant la syntaxe habituelle de déclaration qui associe un type et un nom :

Personne jean, albertine; 

jean et albertine sont deux variables du type Personne. Comme il s’agit d’un type non primitif (char, int...), on dit qu’il s’agit d’instances de la structure Personne. Le terme instance rappelle que le nom et l’âge sont des caractéristiques propres à chaque personne.

images/C03RI01.png

On utilise une notation particulière pour atteindre les champs d’une instance :

jean.age = 50;  // l'âge de jean  
printf("%s",albertine.nom); // le nom d'albertine 

Cette notation relie le champ à son instance.

2. Constitution d’une structure

Une structure peut contenir un nombre illimité de champs. Pour le lecteur qui découvre...

Structures et fonctions

Ce sont les fonctions qui opèrent sur les structures. Il est fréquent de déclarer les structures comme variables locales d’une fonction dans le but de les utiliser comme paramètres d’autres fonctions. Quel est alors le meilleur moyen pour les transmettre ? Nous avons à notre disposition les trois modes habituels, par valeur, par adresse (pointeur) ou par référence.

1. Passer comme paramètre une structure par valeur

Le mode par valeur est indiqué si la structure est de petite taille et si ses valeurs doivent être protégées contre toute modification intempestive de la part de la fonction appelée. Ce mode implique la recopie de tous les champs de l’instance dans la pile, ce qui peut prendre un certain temps et consommer des ressources mémoire forcément limitées. Dans le cas des fonctions récursives, la taille de la pile a déjà tendance à grandir rapidement, il n’est donc pas judicieux de la surcharger inutilement.

Toutefois, cette copie empêche des effets de bord puisque c’est une copie de la structure qui est passée.

void afficher(Nombre n)  
{  
  switch(n.t_nb)  
  {  
  case t_int:  
    printf("%d\t",n.val.nb_i);  
    break;  
  case t_float:  
    printf("%f\t",n.val.nb_f);  
    break;  
  case t_double:  
    printf("%f\t",n.val.nb_d);  
    break;  
  }  
} 

2. Passer comme paramètre une structure par référence

Ce mode constitue une avancée considérable, puisque c’est la référence (adresse inaltérable) de la structure...

La bibliothèque standard du C

Avec les structures et l’allocation de la mémoire, nous nous rendons compte qu’un langage doit s’appuyer sur des librairies système pour construire des applications complètes. Le langage C++ possède sa propre librairie, mais nombre de programmeurs utilisent toujours les fonctions standards du langage C.

1. Les fonctions communes du langage C <stdlib.h>

La librairie standard stdlib.h contient des fonctions d’ordre général. Certaines fonctions peuvent être d’ailleurs déclarées dans d’autres en-têtes.

Voici une liste résumant quelques fonctions intéressantes pour le développement courant. Il est judicieux de consulter l’ouvrage Le langage C de Kernighan et Ritchie, ou bien une documentation fournie avec le compilateur pour connaître à la fois la liste complète des fonctions et en même temps leur signature. 

Le Kernighan et Ritchie est l’ouvrage de référence écrit par les créateurs du langage C. Il est toujours édité et mis à jour à partir des évolutions du langage C.

Fonctions

Utilité

atoi, atof, strtod...

Fonctions de conversion entre un type chaîne et un type numérique.

getenv, setenv

Accès aux variables d’environnement système.

malloc, calloc

Allocation de mémoire.

rand, abs

Fonctions mathématiques.

La bibliothèque standard stdlib contient aussi des macro-instructions basées sur la syntaxe #define :

Macro

Utilité

__min, __max

Donne les valeurs min et max de deux arguments.

NULL

Littéralement (void*)0.

Un petit exemple montre comment utiliser la bibliothèque :

char* lecture = new char[500];  
printf("Nombre ? ");  
scanf("%s",lecture);  
  
double nombre = atof(lecture);  
double pi = 3.14159265358;  
  
printf("Le nombre le plus grand est %2f\n",__max(nombre,pi)); 
images/02RI02.png

2. Chaînes <string.h>

Le langage C++ gère toujours ses littérales de chaîne au format char* défini par le langage C. Aussi est-il important de connaître les principales fonctions de la bibliothèque string.h.

Fonctions

Utilité

memcpy, memcmp, memset

Vision mémoire...

Exercices pratiques

Voici un programme à réaliser en C++ qui associe structures et bibliothèque standard C. Il s’agit d’une petite base de données décrivant des étoiles et des constellations.

1. Les structures

Le programme comprend deux structures Etoile et Constellation, lesquelles sont instanciées sous les noms respectifs proxima et grande_ourse.

/*  
 * structures de données et instances  
 */  
   
struct Etoile {  
    char* nom;  
    float distance_al;  
};  
  
struct Constellation {  
    Etoile* etoiles; 
    int nombre; 
} grande_ourse;  
  
Etoile proxima; 

2. La fonction d’initialisation

La fonction d’initialisation est une application directe de la syntaxe pour définir les valeurs des champs d’une structure. On note aussi l’utilisation de l’opérateur de conversion explicite (char*) pour affecter un char* avec une valeur const char*.

// initialise une constellation  
void init()  
{  
    printf("Initialisation\n");  
    grande_ourse.etoiles = new Etoile[3];  
    grande_ourse.etoiles[0].nom = (char*) "Alioth";  
    grande_ourse.etoiles[0].distance_al = 81;  
  
    grande_ourse.etoiles[1].nom = (char*) "Dubhe";   
    grande_ourse.etoiles[1].distance_al = 80;  
   
    grande_ourse.etoiles[2].nom = (char*) "Zeta";  
    grande_ourse.etoiles[2].distance_al = 78;  
  
    grande_ourse.nombre = 3;  
} 

3. Les fonctions d’affichage

Il y a d’abord la fonction to_string() chargée de représenter une instance sous la forme d’une chaîne. Nous retrouverons ce mécanisme comme méthode (fonction intégrée) de la plupart des classes C++.

// transforme une instance d'étoile en chaîne  
char*...