Annonce

Réduire
Aucune annonce.

Cours langage C n°12 - Les structures

Réduire
Ceci est une discussion importante.
X
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Cours langage C n°12 - Les structures

    Les structures

    Une structure est comme un tableau, qui sera constitué d'un certains nombre d'objets mais qui ne seront pas forcément du même type.

    Exemple de syntaxe

    Code:
    struct objet
    {
        char tab[50];
        int taille;
    } objet;
    Notre structure se nomme objet, et comprend un tableau de caractères (50 maximum) et un entier dont la variable se nomme taille.

    Création d'une structure

    Les structures sont soit créées dans le fichier.c et en dehors de la fonction principale main, soit et là on préférera toujours, écrire notre structure dans le fichier.h, c'est à dire le fichier d'en-tête du fichier.c

    On le placera dans notre cas toujours dans le fichier d'en-tête...

    Imaginons que nous ayons créé un fichier program.c et son fichier d'en-tête program.h, voici à quoi ressemblera program.h

    program.h

    Code:
    #ifndef PROGRAM_H_INCLUDED
    #define PROGRAM_H_INCLUDED
    
    struct objet /* création d'une structure */
    {
        char tab[50];
        int taille;
    } objet;
    
    #endif
    program.c

    Code:
    #include <stdio.h>
    #include "program.h" /* ne pas oublier */
    
    int main(void)
    {
        /* code */
    
        return 0;
    }
    Déclaration d'une structure

    C'est assez simple, dans program.c vous déclarez en plaçant le mot clé struct devant le nom de la structure

    Code:
    struct objet o; /* déclaration de la structure objet nommée o */
    Enregistrement et accès aux champs d'une structure

    Il y a deux possibilité, soit vous avez déclaré
    1. une structure
    2. une adresse de structure


    On ne verra pour ce cours que le cas où l'on déclare une structure...

    Pour une structure simple, on utilisera le point '.' pour accéder à notre champ.

    Pour le champ taille de ma structure objet, on fera de cette façon

    Code:
    #include <stdio.h>
    #include <string.h> /* Pour strlen */
    #include "program.h" /* Pour ma structure objet */
    
    int main(void)
    {
        const char *chaine = "Bonjour";
        int t = strlen(chaine); /* longueur de la chaîne "Bonjour" */
    
        struct objet o; /* déclaration de ma structure objet nommée o */
    
        o.taille = t; /* enregistrement de la valeur de la variable t dans le champ taille de ma structure objet */
    
        printf("%d caractères\n", o.taille); /* 7 caractères */
    
        return 0;
    }
    C'est bien beau, mais ce qui m'intéresse c'est plutôt d'accéder à mon tableau de caractères, eh bien... que cela ne tienne!

    Code:
    #include <stdio.h>
    #include <string.h>
    #include "program.h"
    
    int main(void)
    {
        const char *chaine = "Bonjour";
        int t = strlen(chaine); /* longueur de la chaîne "Bonjour" */
    
        struct objet o; /* déclaration de ma structure objet nommée o */
    
        strcpy(o.tab, chaine); /* copie du contenu de la variable chaine dans le champ tab de la structure objet */
        o.taille = t;
    
        printf("%s a %d caractères\n", o.tab, o.taille); /* Bonjour a 7 caractères */
    
        return 0;
    }
    Comme on le voit ci-dessus, on utilise toujours le point '.' pour accéder à notre champ tab, et comme un tableau de caractères, on le copiera avec strcpy

    Interdit

    Il est totalement interdit d'enregistrer une chaîne de caractères dans un champ de structure de cette façon

    Code:
    o.tab = chaine; /* plantage du programme */
    EXERCICES

    Exercice n°1

    Il est l'heure pour vous d'aller faire vos achats pour le repas de midi dans votre supermarché préféré. Pour cela vous allez
    • créer deux fichiers supermarche.c et supermarche.h
    • créer une structure article dont les champs seront les suivants: const char nom[20], double prix, int quantite dans le fichier d'en-tête de votre programme.
    • créer une fonction nommée afficher, prenant en paramètre une structure article dont le prototype est ci-dessous


    Code:
    void afficher(struct article art);
    et permettant d'afficher sous cette forme

    nom: poireaux
    prix: 1,49 euros
    quantité: 3
    • créer plusieurs articles (3 minimum) dans un tableau de structures (écris directement dans le programme sans demande à l'utilisateur)



    Code:
    struct article mesArticles[3]; /* déclaration d'un tableau d'articles /*
    • afficher à l'aide d'une boucle for, tous les articles que vous avez acheté à l'aide de la fonction afficher


    Exercice n°2
    • Définir une structure de livre contenant :
      – un titre
      – un auteur
      – une année de parution
    • Créer et initialiser deux variables correspondant à deux livres différents
    • Afficher les informations des deux livres
    • Modifier la date de parution du deuxième livre
    • Afficher les informations du deuxième livre

    Merci de m'avoir lu et à bientôt pour le prochain cours
    Dernière modification par fred, 21 juillet 2014, 13h17.

  • #2
    Bonjour à tous,

    Lorsqu'on combine structure et tableau :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct graph graph;
    
    void initialiserCoordonnes(graph *Point);
    
    struct graph
    {
        int x;
        int y;
    };
    
    int main( int argc, char argv[])
    {
        graph point;
    
        initialiserCoordonnes(&point);
        printf("%d", point.x);
        printf("%d", point.y);
    
    }
    
    void initialiserCoordonnes(graph *Point)
    {
        (*Point).x = 0;
        Point -> y = 0;
    }
    Pourquoi doit-on taper (*Point).x et non *(Point.x) pour accéder à la valeur de la variable ?
    Dernière modification par shirocen, 31 décembre 2014, 14h36.
    deux et deux font cinq

    Commentaire


    • #3
      Tout simplement parce-que tu déréférences la variable Point. On te demande en paramètre de fonction initialiserCoordonnes une adresse de type graph.
      Pour avoir sa valeur il faut la déréférencer.

      Plus simple que (*Point).x préfère Point->x

      Commentaire


      • #4
        @Fred',

        Ok ok mais le pointeur "*Point" n'a aucune valeur sur (*point) puisque je l'ai déclaré comme type "graph".

        Nous sommes d'accord que *Point permet d'accéder à la valeur de la variable. Or, le pointeur "point" a été déclaré

        avec le type "graph" donc il y a : - Point.x
        - Point.y

        Mais je ne vois pas comment on peut faire seulement (*Point) ?

        Je ne comprends pas ton terme "déréférences".
        Dernière modification par shirocen, 31 décembre 2014, 16h18.
        deux et deux font cinq

        Commentaire


        • #5
          Je ne comprends pas ton terme "déréférences".
          Ce terme est dans le cours sur les pointeurs, je pense que cette syntaxe n'est pas suffisamment aboutie pour aller plus loin dans le cours.
          C'est représentatif de ce code par exemple

          Code:
          #include <stdio.h>
          
          int main(void)
          {
              int n = 2;
              int *p = &n;
          
              printf("%d\n", *p) /* Affichage de la valeur lors du déréférencement, soit 2 */
              *p = 5; /* déréférencement de p, on modifie par la mémoire la variable n */
          
              printf("%d\n", n); /* Affichage de la valeur 5 */
          
              return 0;
          }
          Donc si on suit cette logique, on a une adresse de type graph (graph *Point), que l'on doit déréférencé (*Point) pour avoir sa valeur x, (*Point).x

          On peut y accéder directement par son adresse grâce à l'opérateur ->

          Commentaire


          • #6
            Mhhhh toujours pas compris :s

            Sinon pour le code, aucun soucis mais cette histoire de structure et de pointeur..

            Reprenons déjà à la base, un pointeur sur un int se comporte t-il de la même façon qu'un pointeur sur une structure ?

            Donc si on suit cette logique, on a une adresse de type graph (graph *Point), que l'on doit déréférencé (*Point) pour avoir sa valeur x, (*Point).x
            Tu peux développé cette partie s'il-te-plaît ?
            Dernière modification par shirocen, 31 décembre 2014, 16h49.
            deux et deux font cinq

            Commentaire


            • #7
              Tout à fait c'est une adresse mémoire...

              EDIT: Tiens un petit test pour voir ta compréhension des pointeurs.

              Code:
              #include <stdio.h>
              
              typedef struct graph graph;
              
              void initialiserCoordonnes(int *value);
              
              struct graph
              {
                  int x;
                  int y;
              };
              
              int main(void)
              {
                  graph point;
              
                  initialiserCoordonnes(...) /* à compléter pour initialiser x */;
                  initialiserCoordonnes(...) /* à compléter pour initialiser y */;
                  printf("%d\n", point.x);
                  printf("%d\n", point.y);
              
                  return 0;
              
              }
              
              void initialiserCoordonnes(int *value)
              {
                  *value = 0;
              }
              EDIT2: Note que c'est le cours n°13 qui correspond le plus à ton problème.
              Dernière modification par fred, 31 décembre 2014, 17h03.

              Commentaire


              • #8
                Aucun soucis là non plus :s :
                Code:
                #include <stdio.h>
                
                typedef struct graph graph;
                
                void initialiserCoordonnes(int *value);
                
                struct graph
                {
                    int x;
                    int y;
                };
                
                int main(void)
                {
                    graph point;
                
                    initialiserCoordonnes((&point.x)) /* à compléter pour initialiser x */;
                    initialiserCoordonnes((&point.y)) /* à compléter pour initialiser y */;
                    printf("%d\n", point.x);
                    printf("%d\n", point.y);
                
                    return 0;
                
                }
                
                void initialiserCoordonnes(int *value)
                {
                    *value = 0;
                }
                Merci Fred' de te donner tant de mal !

                Mais le problème persiste, j'pige pas pourquoi il faut l'écrire comme ça.. :/
                Dernière modification par shirocen, 31 décembre 2014, 17h13.
                deux et deux font cinq

                Commentaire


                • #9
                  Pas exactement!

                  Code:
                  initialiserCoordonnes((&point.x)) /* à compléter pour initialiser x */;
                      initialiserCoordonnes((&point.y)) /* à compléter pour initialiser y */;
                  mais plutôt

                  Code:
                  initialiserCoordonnes(&(point.x)) /* à compléter pour initialiser x */;
                      initialiserCoordonnes(&(point.y)) /* à compléter pour initialiser y */;
                  Même si le résultat est le même, la compréhension est différente, tu considères que &point.x représente une adresse certes, mais laquelle ? celle de point ou celle de point.x, ici tu as de la chance, mais précisément c'est l'adresse de la valeur x de la structure Point. C'est important pour d'autres principes.

                  Pourquoi déréférencer *(point.x) je ne pige pas. Si on décompose point.x est une valeur, elle ne peut donc pas être déréférencé, ce n'est pas une adresse. N'oublions pas que les parenthèses imposent une priorité.

                  Alors que (*point).x est le déréférencement d'une adresse, on aura donc la valeur point, puis point.x, valeur de x de la structure Point.

                  Je sais pas comment mieux expliqué, sinon voir le cours n°13 qui peut mettre la puce à l'oreille peut-être...

                  Commentaire


                  • #10
                    Excuses-moi Fred' mais j'associe l'écriture "*Point" à la valeur que pointe le pointeur "Point", Donc lorsqu'il est écrit :
                    Code:
                    (*Point).x = 0;
                    Je résonne comme ça : On remplace (*Point) par la valeur de la variable qu'il pointe, chose improbable ?

                    -> Ex : 9999.x = 0 ?

                    Je suis à côté non ? :v Pourtant, je comprend tous tes exemples mais franchement je ne vois pas le truc.
                    Dernière modification par shirocen, 31 décembre 2014, 17h57.
                    deux et deux font cinq

                    Commentaire


                    • #11
                      Non, tu comprends mal, si tu déréférences une adresse dont le type est une structure, alors la variable sera de type structure.

                      Commentaire


                      • #12
                        Oulalalalala je crois que tu tiens quelque chose ! Tu pourrais me donner un exemple ?!
                        deux et deux font cinq

                        Commentaire


                        • #13
                          Code:
                          #include <stdio.h>
                          #include <string.h>
                          
                          typedef struct graph graph;
                          
                          struct graph
                          {
                              int x;
                              int y;
                          };
                          
                          int main(void)
                          {
                              graph point, another;
                          
                              graph *p = &point;
                          
                              *p = another;
                          
                              int n = memcmp(&another, &point, sizeof(graph));
                          
                              printf("%d\n", n); /* n vaut 0 */
                          
                              return 0;
                          
                          }
                          memcmp

                          Commentaire


                          • #14
                            Hum' :x

                            Je pense vraiment que j'ai raté quelque chose, je vais relire mes cours et essayer d'éclaircir tout

                            je reviendrais vers toi si vraiment j'y arrive pas.

                            Merci pour ton aide Fred'

                            Toujours cette interrogation : Comment un pointeur de type "Structure" peut-il pointé vers différente valeurs alors

                            qu'un pointeur ne peut contenir qu'une seule adresse ?

                            EDIT : Un pointeur est créé pour chaque variables contenues dans la structure ?
                            Dernière modification par shirocen, 31 décembre 2014, 18h44.
                            deux et deux font cinq

                            Commentaire


                            • #15
                              Ça devrait être plus simple pour toi en comparant par valeur

                              Code:
                              #include <stdio.h>
                              
                              typedef struct graph graph;
                              
                              struct graph
                              {
                                  int x;
                                  int y;
                              };
                              
                              int main(void)
                              {
                                  graph point, another;
                              
                                  another.x = 5;
                                  another.y = 9;
                              
                                  graph *p = &point;
                              
                                  *p = another;
                              
                                  printf("%d, %d\n", point.x, point.y);
                              
                                  return 0;
                              
                              }
                              Difficile de jongler avec les pointeur, hein ?

                              Commentaire

                              Chargement...
                              X