Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème tuto apprendre C++

erreur C2369

    19 mai 2022 à 20:48:30

    Bonsoir tout le monde!

    En suivant les différentes étapes du cours en libre accès permettant d'apprendre le C++, à l'étape où il est nécessaire de parcourir un tableau statique, je me retrouve avec deux erreurs :

       - C2369    'meilleursScores' : redéfinition ; indices différents (ligne 8, 9, 10 et 11)

       - C2086    'int meilleursScores[5]' : redéfinition (ligne 12)

    #include <iostream>
    
    using namespace std;
    
    int const nombreMeilleursScores(5);           //La taille du tableau
    int meilleursScores[nombreMeilleursScores];   //Déclaration du tableau
    
    int meilleursScores[1] = { 118218 };  //Remplissage de la première case
    int meilleursScores[2] = { 100432 };  //Remplissage de la deuxième case
    int meilleursScores[3] = { 87347 };   //Remplissage de la troisième case
    int meilleursScores[4] = { 64523 };   //Remplissage de la quatrième case
    int meilleursScores[5] = { 31415 };   //Remplissage de la cinquième case
    
    int main()
    {
        for (int i(0); i < nombreMeilleursScores; ++i)
        {
            cout << meilleursScores[i] << endl;
        }
    }

    et voici mon code.

    En espérant que vous pourrez m'aider, merci d'avance pour vos réponses.

    -
    Edité par ThibautBournonville 19 mai 2022 à 20:52:36

    • Partager sur Facebook
    • Partager sur Twitter
      19 mai 2022 à 21:44:46

      salut,

      Ton problème vient de ce que ton code ne fait pas ce que  tu crois, ou plutot, ce que tu attends qu'il fasse...

      Car, lorsque le compilateur voit une instruction qui prend la forme de

      UN_TYPE UN_NOM = UNE_VALEUR;

      il va en réalité considérer qu'il y a deux instructions là dedans:

      • D'abord la déclaration de la donnée, qui correspond à UN_TYPE UN_NOM; c'est juste une instruction qui dit "tu sais quoi, je décide qu'il existe une donnée dont le nom est UN_NOM et dont le type est UN_TYPE
      • Puis il y a la définition de la valeur pour cette donnée qui correspond à UN_NOM = UNE_VALEUR; et qui dit en gros "tu  sais quoi? la donnée UN_NOM, je veux lui donner la valeur de UNE_VALEUR"

       De même, lorsque tu écrit un code proche de

      int meilleursScores[nombreMeilleursScores];

      tu dis en réalité au compilateur que "j'ai décidé qu'il y aurait une donnée nommée meilleursScores, et qui est en mesure de représenter nombreMeilleursScore données de type int".

      C'est donc une déclaration.

      Jusque là, tout va bien, vu que le compilateur ne connait que ce qu'il a déjà lues avant d'arriver à la ligne qu'il est occupé à traiter, tout ce qu'il connait lorsqu'il commence à traiter la ligne 6, c'est... ce qu'on lui a dit à la ligne 5, à savoir, qu'il existe une donnée (constante) de type int appelée nombreMeilleursScores, et dont la valeur est 5.

      C'est pour les lignes suivantes que les choses vont se corser, car, alorrs qu'il a bien compris que meilleursScores était une donnée permettant de représenter cinq entier à la ligne 6, voilà-t-y qu'il retrouve à la ligne 8 une déclaration de la variable nommée meilleursScores qui n'est absolument pas la même que celle qu'il a croisée à la  ligne 6, vu que la ligne 8 contient (si on ignore la définition de valeur) int meilleursScores[1];

      Et, du coup, il a toutes les raisons de ne pas être content, car cette instruction va générer un conflit, en plus de contrevenir à une règle appelée ODR (one declaration rule: chaque élément ne peut être déclaré qu'une seule et unique fois), car si le compilateur voulait respecter ce que tu lui dit -- et le compilateur n'a pas d'autre choix que de respecter tes instructions -- il se retrouverait avec deux données qui portent le même nom, mais qui représentent des choses différentes, à savoir: une donnée capable de représenter 5 entiers l'un à  la suite de l'autre pour  la ligne 6, et une donnée capable de ne représenter que un seul entier à  la ligne 8.

      Tu imagines un peu la détresse psychologique dans laquelle tu  serait si tu devais faire en sorte de respecter ces deux instructions ????

      Le compilateur, lui, il va avoir une manière bien à lui de résoudre le problème: il va simplement te dire que tu dois commencer par te mettre d'accord avec toi même, avant d'arrêter de travailler.

      Et, bien sur, ce qui est vrai pour la ligne 8 l'est également pour les lignes 9, 10, 11 et 12 ;)

      Maintenant que tu as (je l'espère) compris ce qui se passe, on peut commencer à  t'expliquer comment résoudre le problème.

      Hé bien, ce que tu dois faire aux lignes 8, 9, 10, 11 et 12, c'est que tu dois faire une définition et non une déclaration.  Comment? ben, c'est tout simple: tu retire la notion de type (le mot clé int).

      Sauf que, en fait, ce ne sera pas suffisant dans ton cas.  Car il y a une chose qu'il faut savoir dans ton cas: l'indice (la valeur que tu places entre [ et ] )  du premier élément d'un tableau est toujours égale à 0, ce qui fait que le nombre correspondant au nombre d'éléments de ton tableau est en réalité l'indice du premier élément qui ne fasse pas partie du tableau.

      Cela signifie que dans ton cas, les indices représentant les éléments de ton tableau sont 0, 1, 2, 3 et 4.  Tu remarqueras que cela fait bel et bien 5 éléments, et que l'élément qui aurait dés lors l'indice 5 se trouve ... juste après le dernier élément valide du tableau ;)

      Au final, il faudra juste remplacer les lignes

      int meilleursScores[1] = { 118218 };  //Remplissage de la première case
      int meilleursScores[2] = { 100432 };  //Remplissage de la deuxième case
      int meilleursScores[3] = { 87347 };   //Remplissage de la troisième case
      int meilleursScores[4] = { 64523 };   //Remplissage de la quatrième case
      int meilleursScores[5] = { 31415 };   //Remplissage de la cinquième case

      par les lignes

      meilleursScores[0] = { 118218 };  //Remplissage de la première case
      meilleursScores[1] = { 100432 };  //Remplissage de la deuxième case
      meilleursScores[2] = { 87347 };   //Remplissage de la troisième case
      meilleursScores[3] = { 64523 };   //Remplissage de la quatrième case
      meilleursScores[4] = { 31415 };   //Remplissage de la cinquième case

      pour que ton code puisse fonctionner "avec un minimum de changements"

      Après, ton code présente d'autres problèmes, dont le fait que les données variables (comprends : dont la valeur risque d'être modifiée au fil du temps) déclarées comme étant des variables globales (qui sont déclarées hors de toute fonction, comme c'est le cas pour meilleursScores), C'EST MAL pour toute une série de raisons que je pourrai t'expliquer si tu en fais la demande.

      On pourrait aussi te dire que l'utilisation de la directive using namespace std;, c'est pas vraiment la meilleure idée du siècle (tu peux lire cette intervention de ma part sur un autre forum pour comprendre pourquoi).

      Mais chaque chose en son temps.  Dans l'immédiat, je voudrais m'assurer que tu as compris le pourquoi du comment du coup de gueule du compilateur, et la manière d'y remédier ;)


      • Partager sur Facebook
      • Partager sur Twitter
      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
        19 mai 2022 à 21:45:00

        Salut,

        Si le cours que tu suis ne t'as pas encore montrer la différence en déclaration, définition et assignation avant de te parler de tableau intégré, je te pris de changer de cours.

        Note: Une simple recherche sur le Forum t'aidera a trouver un bon cours sur le C++.

        • Partager sur Facebook
        • Partager sur Twitter

        Ton présent détermine ton futur et la connaissance te placera au dessus de ta génération .

          19 mai 2022 à 22:56:10

          Les lignes 8 à 12 il faut les mettre dans le main car on ne peut pas avoir d'instructions autres que des déclarations/définitions en dehors de fonctions. Il faut aussi enlever le "int" et pourquoi pas les accolades qui ne servent à rien et les indices de tableau commencent à 0 donc les 5 premiers éléments ont les indices 0, 1, 2, 3, 4.

          En C++ il existe une syntaxe plus simple quand on veut juste "parcourir une collection" :

          for (int score : meilleursScores) {
            std::cout << score << std::endl;
          }


          Sinon tu pouvais aussi tout simplement donner les valeurs du tableau directement au moment de le déclarer :

          int meilleursScores[] = {
            118218,
            100432,
            87347,
            64523,
            31415
          };

          Aussi, ça ne sert à rien de stocker le nombre de meilleurs scores dans une variable à part, car c'est simplement la taille du tableau, que tu peux récupérer directement en faisant

          std::size(meilleursScores);

          D'ailleurs si tu connais déjà à l'avance tous les éléments du tableau tu n'es pas obligé de préciser la taille du tableau (comme je l'ai fait plus haut), il aura directement la taille correspondant au nombre d'éléments que tu lui a donné (à noter que cette astuce ne fonctionnera pas si le tableau est une variable membre dans une classe).

          • Partager sur Facebook
          • Partager sur Twitter
            20 mai 2022 à 1:04:59

            @koala01: bravo pour ta patience.
            Mon compilateur n'est pas rancunier. Je fais des erreurs et il accepte toujours de compiler mes codes. :)
            • Partager sur Facebook
            • Partager sur Twitter

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

              20 mai 2022 à 10:23:07

              Bonjour à vous

              Merci beaucoup pour toute vos réponses! En utilisant chaque solutions, j'ai réussi à ne plus avoir d'erreurs! J'ai compris je déclarais ma variable plusieurs fois avec à chaque fois une valeur différente pour celle-ci. Voici mon code actuellement :

              #include <iostream>

              int main()
              {
              int meilleursScores[] = { //Déclaration du tableau

              meilleursScores[0] = 118218, //Remplissage de la première case
              meilleursScores[1] = 100432, //Remplissage de la deuxième case
              meilleursScores[2] = 87347, //Remplissage de la troisième case
              meilleursScores[3] = 64523, //Remplissage de la quatrième case
              meilleursScores[4] = 31415, //Remplissage de la cinquième case
              };

              for (int score : meilleursScores)
              {
              std::cout << score << std::endl;
              }
              }

              @koala01 : je dis jamais non pour un peu de connaissances en plus, donc oui pourquoi pas m'expliquer tout ce qui ne va pas.

              -
              Edité par ThibautBournonville 20 mai 2022 à 10:24:48

              • Partager sur Facebook
              • Partager sur Twitter
                20 mai 2022 à 14:30:12

                Et pourquoi ne pas essayer d'entrer toutes les valeurs sur un seul énoncé lors de la déclaration / définition comme on te l'a suggéré?
                Et tu n'as même pas besoin de donner la longueur. Si tu en rajoutes, tu n'aurais pas besoin de modifier le code.
                Tu utilises size() pour savoir la longueur.
                • Partager sur Facebook
                • Partager sur Twitter

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

                  20 mai 2022 à 14:35:43

                  Comme ceci?

                  #include <iostream>
                  
                  int main()
                  {
                      int meilleursScores[] = {                     //Déclaration du tableau
                          118218,                           //Remplissage de la première case
                          100432,                           //Remplissage de la deuxième case
                          87347,                            //Remplissage de la troisième case
                          64523,                            //Remplissage de la quatrième case
                          31415,                            //Remplissage de la cinquième case
                      };
                  
                      for (int score : meilleursScores){
                          std::cout << score << std::endl;
                      }
                  }



                  • Partager sur Facebook
                  • Partager sur Twitter
                    20 mai 2022 à 15:05:27

                    Alors, ça marche? Le for sous cette forme est tout à fait adéquat.
                    • Partager sur Facebook
                    • Partager sur Twitter

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

                      20 mai 2022 à 15:11:58

                      ThibautBournonville a écrit:

                      Comme ceci ?

                      Oui, mais comme tu t'en doute les meilleurs scores sont fait pour être battu ! Alors il serait judicieux de les stoker dans un fichier puis de les recharger lors de l'ouverture du programme. 

                      De nos jours, on utiliserait plutôt un std::array pour faire un tableau de taille fixe.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        20 mai 2022 à 15:14:43

                        Si c'est bien de taille fixe qui est souhaité.
                        Sinon, il y a std::vector
                        • Partager sur Facebook
                        • Partager sur Twitter

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

                          20 mai 2022 à 18:13:00

                          Ce n'est pas le meilleur cours à suivre (tu auras sûrement d'autres commentaires)
                          Tu pourrais suivre celui-ci:


                          https://zestedesavoir.com/tutoriels/822/la-programmation-en-c-moderne/

                          • Partager sur Facebook
                          • Partager sur Twitter

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

                            20 mai 2022 à 21:51:26

                            Le pourquoi est expliqué dans ce message: https://openclassrooms.com/forum/sujet/mooc-c?page=7#message-86545267

                            Si tu veux un cours qui ne t'apprends pas plein de connerie, tu peux suivre celui de Zeste de Savoir.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              22 mai 2022 à 20:50:54

                              Je vois, merci beaucoup pour vos conseil!

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Problème tuto apprendre C++

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