print · rss · source

< Les fonction d'entrée/sortie | TutoCFrench | Les fonctions de manipulation de fichiers >


Types de données composés et type dérivés

Notions :

  • struct
  • enum
  • union
  • typedef
  • initialisation
  • déclaration
  • utilisation
  • opérateurs . et ->

Les structures

Une structure est une juxtaposition de plusieurs données regroupées en une entité.

Déclaration d'une structure

La déclaration d'une structure se fait par le mot réservé struct suivi d'une liste de déclaration de variables entre accolades. Attention au ; à la fin des accolades ! :

struct nom
{
type champ1;
type champ2;
...
type champn;
};

Par exemple :

struct employe {
    int age;
    char profession[50];
    int salaire;
};

Note : en principe, on définit une structure en dehors de la fonction main pour lui donner une portée globale.

Affectation et manipulation des structures

Il est possible d'affecter une structure lors de sa déclaration :

struct employe robert = {32, "informaticien", 1200};

Contrairement aux tableaux, il est possible d'utiliser l'opérateur = pour affecter une structure à partir d'une autre :

struct employe lucien, robert = {32, "informaticien", 1200};
lucien = robert;

Pour accèder aux membres de la structure, on utilise l'opérateur '.' (point) concaténé au nom de la structure. Cela permet d'affecter une structure élément par élément :

struct employe robert;

robert.age = 32;
strcpy(robert.profession, "informaticien");
robert.salaire = 1200;

printf("Robert a %d ans et il est %s\n", robert.age, robert.profession);

Attention, on ne peut utiliser les opérateurs arithmétiques ou les opérateurs de comparaison sur des structures.

Les champs

Les éléments d'une structure peuvent aussi être des portions d'entiers, ce qui permet de stocker plusieurs variables sur un seul entier (économie de place). On parle de champs de bits pour qualifier ces données plus petites :

struct candidat {
    char sexe : 1;
    char age  : 7;
    char profession[50];
    int salaire;
};

Pointeurs de structures

Il est possible de créer le type pointeur de structure et d'accèder aux membres d'une structure à partir d'un pointeur sur celle ci :

struct employe *p;

p = &robert;
printf("Robert est %s\n", (*p).profession);

Mais l'ecriture précédente est complexe. Une facilité est offerte par l'opérateur ->. Ainsi, les deux écritures ci-dessous sont équivalentes :

  • (*ptr).nom
  • ptr->nom

On aurait donc pu écrire :

printf("Robert est %s\n", p->profession);

Les unions

Les unions permettent de stocker un choix de plusieurs choses en une même zone mémoire. La définition d'une union est semblable à celle d'une structure, de même que la syntaxe d'accès. La différence est qu'on ne peut stocker qu'un seul élément à la fois.

Les énumérations

Une énumération permet de définir des constantes pour une liste de valeurs. Le compilateur assigne une valeur par défaut à chaque élément de la liste en commençant par 0 et en incrémentant à chaque fois. Par exemple :

enum statut_marital { celibataire, marie, divorce, veuf };

Il est aussi possible d'assigner explicitement des valeurs :

enum statut_marital { celibataire = 1, marie = 2, divorce = 3, veuf = 4 };

La variable s'utilise alors comme dans l'exemple suivant :

struct candidat {
    char sexe : 1;
    char age  : 7;
    enum statut_marital statut_m;
    char profession[50];
    int salaire;
};

struct candidat paul;
paul.statut_m = celibataire;

typedef

Cette directive permet d'assigner un nouveau nom à un type de données au choix. On l'utilise par commodité :

typedef struct employe Employe;

Employe robert = {32, "informaticien", 1200};

Exercices

  1. "annuaire.c" : on souhaite créer un programme d'annuaire très simplifié qui associe à un nom de personne un numéro de téléphone :
    1. Créer une structure Personne pouvant contenir ces informations (nom et téléphone). Le nom peut contenir 32 caractères et le numéro 16 caractères.
    2. Créer une nouvelle structure qui va représenter le carnet d'adresses. Cette structure Carnet contiendra un tableau de 20 Personne et un compteur indiquant le nombre de personnes dans le tableau.
    3. Créer ensuite une fonction qui crée et qui renvoie une structure Personne contenant un nom et un téléphone passés en argument.
    4. Rajouter une fonction qui affiche les informations contenues dans la structure Personne passée en argument.
    5. Créer une fonction qui ajoute une personne dans un carnet.
    6. Créer une fonction qui affiche un carnet.
    7. Faire un programme qui demande de saisir 5 personnes, qui les ajoute dans un carnet puis qui affiche son contenu.
    8. A partir des étapes précédentes, faire un programme gérant un carnet d'adresse. Créer un menu qui propose d'ajouter une nouvelle personne, d'afficher le carnet ou de quitter.
    9. Créer une fonction qui recherche une personne dans un carnet à partir de son nom et qui renvoie un pointeur sur l'entrée correspondante. Ajouter au menu la fonctionnalité correspondante, c'est à dire la possibilité de retrouver un numéro de téléphone à partir d'un nom.

Solutions

annuaire.c

#include <stdio.h>
#include <string.h>

struct Personne {
    char nom[32];
    char telephone[16];
};

struct Carnet {
    struct Personne personne[20];
    int n;
};

struct Personne creer_personne(char nom[], char telephone[])
{
    struct Personne nouv_p;
    strcpy(nouv_p.nom, nom);
    strcpy(nouv_p.telephone, telephone);
    return nouv_p;
}

void afficher_personne(struct Personne p)
{
    printf("Nom: %s\tTelephone: %s\n", p.nom, p.telephone);
    return;
}

void ajouter_personne(struct Carnet *c, struct Personne p)
{
    if (c->n < 20) {
        c->personne[c->n] = p;
        c->n++;
    }
    else 
        printf("Carnet plein\n");
    return;
}

void afficher_carnet(struct Carnet c)
{
    int i;
    for (i=0; i<c.n; i++)
        afficher_personne(c.personne[i]);
    return;
}

struct Personne* chercher_personne(struct Carnet *c, char nom[])
{
    int i;
    for (i=0; i<c->n; i++) {
        if (strcmp(nom, c->personne[i].nom) == 0)
            return &c->personne[i];
    }
    return NULL;
}

int main()
{
    struct Personne nouv_p, *pp;
    struct Carnet carnet;
    char nom[32], telephone[16];
    char choix;

    /* initialisation */
    carnet.n = 0;

    while (1) {
        printf("(a)fficher, (i)nsérer, (c)hercher, (q)uitter\n");
        printf("> ");
        choix = getchar();

        switch(choix) {
            case 'a' :
                afficher_carnet(carnet);
                break;
            case 'i' :
                printf("nom> "); scanf("%s", nom);
                printf("telephone> "); scanf("%s", telephone);
                nouv_p = creer_personne(nom, telephone);
                ajouter_personne(&carnet, nouv_p);
                break;
            case 'c' :
                printf("nom> "); scanf("%s", nom);
                pp = chercher_personne(&carnet, nom);
                if (pp)
                    afficher_personne(*pp);
                else
                    printf("Personne inconnue\n");
                break;
            case 'q' :
                return 0;
                break;
            default :
                printf("Commande inconnue\n");
        }

        do
            choix = getchar();
        while (choix != '\n');

        printf("\n");
    }

    return 0;
}

< Les fonction d'entrée/sortie | TutoCFrench | Les fonctions de manipulation de fichiers >

print · rss · source
Page last modified on February 28, 2008, at 11:23 AM