Partage
  • Partager sur Facebook
  • Partager sur Twitter

Adresses et tableau, prend les mauvaises valeurs..

Tableaux

    21 décembre 2021 à 18:30:48

    Bonjour,

    Je travaille sur un projet et je crée ici des structures de joueurs qui vont pouvoir etre modifiables (argent, position ect) sauf que ici j'ai un probleme, quand je fais un test dans mon main pour voir ce qui ressort de mon sous-prog creation_structures_joueurs et il me renvoie un nombre tres grand dans la console... pour l'argent...

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct joueur
    {
        char pseudo;
        int argent;
        int position;
    
    }t_joueur;
    
    
    int nb_player()
    {
        // demannde le nombre de joueurs
        int nb_joueurs = 1;
        while (nb_joueurs != 2 && nb_joueurs != 3 && nb_joueurs != 4)
        {
            printf("A combien souhaitez-vous jouer ?\n");
            scanf("%d", &nb_joueurs);
        }
        return nb_joueurs;
    }
    
    int creation_structures_joueurs()
    {
        int nombre_joueurs = nb_player();
        t_joueur joueur_x[nombre_joueurs];
        for (int x = 0; x < nombre_joueurs; x++)
        {
            printf("Joueur %d, entrez votre pseudo : ", x+1);
            fflush(stdin);
            gets(&joueur_x[x].pseudo);
            joueur_x[x].argent = 1500;
            joueur_x[x].position = 0;
        }
    }
    
    int main()
    {
        int x = 0;
        t_joueur joueur_x[x];
        creation_structures_joueurs();
        printf("Le joueur %d a %d$ !", x+1, joueur_x[x].argent);
        return 0;
    }
    

    Que faire ?

    • Partager sur Facebook
    • Partager sur Twitter
      21 décembre 2021 à 18:44:06

      Ça commence pas très bien : dans ta fonction main tu crées un tableau joueur_x de taille 0. tu ne va donc pas pouvoir y mettre grand chose !

      Ta fonction creation_structures_joueurs ne modifie en rien ce tableau (Elle a son propre tableau joueur_x qui n'a rien à voir avec celui là.

      Et tu affiches le champ argent de la 1ere case du tableau de la fonction main. case qui n'existe pas puisqu'il en a 0 de case, ça affiche donc n'importe quoi et ça aurait très bien pu planter.   

      -
      Edité par rouIoude 21 décembre 2021 à 18:46:15

      • Partager sur Facebook
      • Partager sur Twitter
        21 décembre 2021 à 18:49:16

        Et pseudo est un simple caractère alors qu'on devrait en mettre plusieurs.
        Ça va te prendre un tableau de char assez long.

        Utilises fgets au lieu de gets

        -
        Edité par PierrotLeFou 21 décembre 2021 à 18:51:32

        • Partager sur Facebook
        • Partager sur Twitter

        Le Tout est souvent plus grand que la somme de ses parties.

          21 décembre 2021 à 19:01:27

          Ok mais du coup j'ai une question : comment renvoyer les tableaux joueur_x[x] ?
          • Partager sur Facebook
          • Partager sur Twitter
            21 décembre 2021 à 19:04:56

            Pour modifier un tableau dans une fonction, le plus simple est de le passer en argument de cette fonction. Le tableau sera alors modifié, pas besoin de le renvoyer par un 'return'.
            • Partager sur Facebook
            • Partager sur Twitter
              21 décembre 2021 à 19:17:01

              Je demanderais le nombre de joueurs dans le main et je passerais le tableau et ce nombre à la fonction.
              • Partager sur Facebook
              • Partager sur Twitter

              Le Tout est souvent plus grand que la somme de ses parties.

                21 décembre 2021 à 20:25:46 - Message modéré pour le motif suivant : Merci d'utiliser le bouton code du forum pour insérer votre code


                  21 décembre 2021 à 20:36:22

                  Utilises le bouton code </> du forum pour poster ton code ! (tu peux modifier ton post, lien modifier en haut à droite du post).
                  Parce qu'il te demande un tableau (adresse de sa première case) pas une case du tableau (qui plus est en dehors du tableau) !

                  -
                  Edité par rouIoude 21 décembre 2021 à 20:38:57

                  • Partager sur Facebook
                  • Partager sur Twitter
                    21 décembre 2021 à 21:20:14

                    Clément 2910 a écrit:

                    Ok mais du coup j'ai une question : comment renvoyer les tableaux joueur_x[x] ?


                    Voilà une phrase qui montre ta mécompréhension.  Il n'y a qu'un seul tableau et c'est joueur_x. Il contient x éléments et pour y accéder tu utiliseras joueur_x[0], joueur_x[1], …, joueur_x[x-1]. joueur_x[x] est un élément qui sera toujours en dehors du tableau et pourra provoquer des erreurs …

                    • Partager sur Facebook
                    • Partager sur Twitter
                      21 décembre 2021 à 22:06:29

                      int creation_structures_joueurs(int x, t_joueur joueur_x)
                      {
                          for (int i = 0; i < x; i++)
                          {
                              printf("Joueur %d, entrez votre pseudo : ", i+1);
                              fflush(stdin);
                              gets(&joueur_x[i].pseudo);
                              joueur_x[i].argent = 1500;
                              joueur_x[i].position = 0;
                          }
                      }
                      
                      int main()
                      {
                          int x = nb_player();
                          t_joueur joueur_x[x];
                          creation_structures_joueurs(x, joueur_x);
                          return 0;
                      }
                      OK J'AI COMPRIS, mais pourquoi ici le gets ya une erreur et pareil pour les 2 lignes apres (suscribed value is not an array, pointer or vector...)
                      • Partager sur Facebook
                      • Partager sur Twitter
                        21 décembre 2021 à 22:42:20

                        Le prototype de ta fonction creation_structures_joueurs est déclaré recevoir un t_joueur or il me semble que c'est un tableau de t_joueur que tu veux envoyer.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          21 décembre 2021 à 23:02:06

                          mais c'est ce que je fais non ? j'initialise mon tableau dans mon main et je l'envoie dans ma fonction ??? que faire ???
                          • Partager sur Facebook
                          • Partager sur Twitter
                            21 décembre 2021 à 23:09:23

                            Salut, tu n'envoies pas ton tableau mais son adresse, et il faut un pointeur pour réceptionner une adresse
                            • Partager sur Facebook
                            • Partager sur Twitter
                              22 décembre 2021 à 1:17:22

                              Clément 2910 a écrit:

                              mais c'est ce que je fais non ? j'initialise mon tableau dans mon main et je l'envoie dans ma fonction ??? que faire ???


                              Ce n'est qu'une question de vocabulaire, mais en C, "initialiser" a un sens précis.

                              int tableau_non_initialise[3];
                              int tableau_initialise[3] = { 4, 5, 6 };
                              

                              Dans ta fonction main, le tableau n'est pas initialisé.

                              Ensuite, le second argument passé à creation_structures_joueurs est un pointeur sur le premier élément du tableau.
                              En effet, si tu te souviens du cours, quand on utilise un identifiant de tableau dans une expression, ça produit généralement un pointeur sur son premier élément.

                              Le gros problème est dans le prototype de fonction

                              int creation_structures_joueurs(int x, t_joueur joueur_x)

                              Le second paramètre devrait être de type pointeur de t_joueur. Or il est de type t_joueur.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                22 décembre 2021 à 1:58:13

                                Tu as deux façons pour le dire:
                                int creation_structures_joueurs(int x, t_joueur *joueur_x)
                                int creation_structures_joueurs(int x, t_joueur joueur_x[])
                                Dans la seconde forme, la notion de pointeur est moins explicite.
                                • Partager sur Facebook
                                • Partager sur Twitter

                                Le Tout est souvent plus grand que la somme de ses parties.

                                  22 décembre 2021 à 9:29:48

                                  Je préfère la seconde forme. Parler de pointeurs dans ce contexte risque d'embrouiller les gens, je trouve plus simple de juste parler de tableaux.

                                  On veut appeler la fonction ainsi :

                                  creation_structures_joueurs(x, joueur_x);
                                  • Paramètre n°1 : 'x' est un 'int'
                                  • Paramètre n°2 : 'joueur_x' est un tableau dont les éléments sont des 't_joueur'.

                                  Donc la fonction doit être déclarée ainsi :

                                  int creation_structures_joueurs(int x, t_joueur joueur_x[])

                                  Et voilà.

                                  Les crochets indiquent qu'il s'agit d'un tableau (on ne met pas la taille dans les crochets), il ne faut pas donc les oublier : c'était l'erreur de Clément2910.

                                  Pas besoin de parler de pointeur, c'est transparent pour le programmeur.

                                  -
                                  Edité par robun 22 décembre 2021 à 9:31:51

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    22 décembre 2021 à 9:52:36

                                    robun a écrit:

                                    Pas besoin de parler de pointeur, c'est transparent pour le programmeur.

                                    On n'a rien à cacher, il a le droit de savoir la vérité ! 

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      22 décembre 2021 à 10:12:58

                                      rouIoude a écrit:

                                      robun a écrit:

                                      Pas besoin de parler de pointeur, c'est transparent pour le programmeur.

                                      On n'a rien à cacher, il a le droit de savoir la vérité ! 

                                      D'autant que la notation tableau est finalement mensongère; Car c'est bien un pointeur qui passé. Justement pour un débutant, la notation pointeur permet de lui rappeler qu'un tableau n'est jamais passé en paramètre. La notation tableau précise l'intention et est à préférer dans des applications plus "professionnelles".
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      En recherche d'emploi.

                                        22 décembre 2021 à 10:18:13

                                        Un bon conseil serait sans doute d'orienter le PO vers une bonne explication des tableaux en C comme par exemple ⇒ https://zestedesavoir.com/tutoriels/755/le-langage-c-1/1043_aggregats-memoire-et-fichiers/4281_les-tableaux/ .

                                        Et, sans entrer trop dans un HS, je plussoie Robun et Dalfab et … la future norme C23 qui recommande l'utilisation de la notation VLA pour éclaircir les intentions en les explicitant dans le prototype des fonctions comme par exemple :

                                        float determinant(size_t m, size_t n, float matrix[n][m]);



                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          22 décembre 2021 à 10:34:48

                                          Il faut donc cacher dans les explications sur les paramètres de tableau le fait que c'est un pointeur. Je ne suis pas d'accord !
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            22 décembre 2021 à 10:50:27

                                            Ah ben non ! c'est bien pour cela que j'ai donné le lien qui «rétablit la vérité» :)

                                            En fait une fois qu'on comprend la différence entre «tableau» et «pointeur» on remarque que mis à part en utilisant un tableau avec sizeof ou l'opérateur unaire &, il sera toujours converti en un pointeur sur son premier élément (norme paragraphe 6.3.2.1.3).

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              22 décembre 2021 à 12:09:25

                                              Merci pour toutes vos réponses ! Vous m'avez bien aidé et j'ai enfin compris :D

                                              Je vais fermer le sujet dans peu de temps si je ne rencontre pas un nouveau problème.

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                22 décembre 2021 à 13:27:39

                                                Ce que je disais, c'était dans le contexte de cette discussion : Clément2910 a besoin de transmettre des tableaux à sa fonction, comment faire ?

                                                Je ne dis pas qu'il faut cacher que ce sont en fait des pointeurs qui sont transmis. Mais il y a une différence entre utiliser des tableaux et savoir comment ils sont gérés, de même qu'entre conduire une voiture et savoir comment fonctionne le moteur.

                                                L'erreur faite par Clément2910 n'était pas liée aux pointeurs, elle provenait d'une confusion sur l'utilisation des crochets (dans une déclaration ça désigne un tableau, mais dans un appel ça désigne un seul élément).

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  23 décembre 2021 à 2:31:58

                                                  White Crow a écrit:

                                                  En fait une fois qu'on comprend la différence entre «tableau» et «pointeur» on remarque que mis à part en utilisant un tableau avec sizeof ou l'opérateur unaire &, il sera toujours converti en un pointeur sur son premier élément (norme paragraphe 6.3.2.1.3).

                                                  Attention, il faut ajouter que ce pointeur sur le premier élément n'est pas une lvalue.
                                                  C'est une erreur que les débutants font très souvent dans ce site. Par exemple:

                                                  struct s {
                                                     char str[10];
                                                     int foo;
                                                  };
                                                  
                                                  void f(struct s *ps) {
                                                     ps->str = "toto";  // Mais pk ça marche pas ?
                                                     ps->foo = 123;
                                                  }




                                                  -
                                                  Edité par Marc Mongenet 23 décembre 2021 à 2:32:11

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    4 janvier 2022 à 8:49:43

                                                    Alors que

                                                    void foo(char bar[]) {
                                                       bar = "abc";
                                                    } 

                                                    ...

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      4 janvier 2022 à 10:28:43

                                                      michelbillaud a écrit:

                                                      Alors que

                                                      void foo(char bar[]) {
                                                         bar = "abc";
                                                      } 

                                                      Ça serait donc mieux d'écrire : 

                                                      void foo(char *bar) {
                                                         bar = "abc";
                                                      }

                                                      sinon ça fait tableau que l'on affecte ! Bien sur ce n'est pas les cas, puisque c'est un pointeur.


                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        4 janvier 2022 à 11:40:26

                                                        L'affectation bar = "abc" a un résultat assez douteux quand bar est un pointeur reçu en paramètre (passage par valeur...)

                                                        Y en a pas un qui est mieux que l'autre, sauf qu'effectivement, le débutant  peut s'imaginer, avec [], qu'il a réussi à affecter le contenu d'un tableau.

                                                        ---

                                                        C'était juste pour évoquer un truc merdique de C (et d'ailleurs je m'y suis mal pris alors je recommence, le travail bâclé contient sa propre punition) :

                                                        la déclaration

                                                        int t[10]
                                                        
                                                        • déclare un pointeur quand c'est un paramètre
                                                        • et un tableau de 10 entiers quand c'est une variable locale ou globale
                                                        void foo(int a[10]) {            // pointeur
                                                           int b[10];                    // tableau
                                                           ....
                                                        }
                                                        

                                                        -
                                                        Edité par michelbillaud 4 janvier 2022 à 11:49:13

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          4 janvier 2022 à 12:03:27

                                                          Pour pinailler c'est un poil plus complexe si on regarde la norme (6.7.6 sections 2 et 3).

                                                          void foo(int a[10] /*ici, au niveau de la visibilité du prototype a est de type tableau d'entiers, quoique … clang/gcc ont un point de vue différent de msvc/icc par exemple */) {
                                                             // ici, au niveau du bloc  de la fonction, a est ajusté en un pointeur sur le premier élément du tableau
                                                             int b[10];                    // tableau
                                                             size_t s = sizeof(b);         // b est un tableau
                                                             b[0]=42;                      // b est ajusté en pointeur sur entier pointant sur le premier élément du tableau b
                                                             // cette écriture est strictement équivalente à :
                                                             *(b+0)=42                     // où b est à nouveau ajusté en …
                                                             ....
                                                          }



                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            4 janvier 2022 à 12:31:41

                                                            et ça a une conséquence sur l'affectation de quelque chose au paramètre a ?

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              4 janvier 2022 à 12:57:18

                                                              oui quand le type des éléments est incomplets. C'est à ce niveau que clang/gcc ont une interprétation différente de msvc/icc de la norme.
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Adresses et tableau, prend les mauvaises valeurs..

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              • Editeur
                                                              • Markdown