Partage
  • Partager sur Facebook
  • Partager sur Twitter

Déboguer un programme

    15 avril 2018 à 11:19:59

    Bonjour,

    je code depuis peu en C++ et je me suis inscrit sur un site nommé France IOI pour progresser .

    J'essaie de résoudre ce http://www.france-ioi.org/algo/task.php?idChapter=766&idTask=1126sujet .J'ai obtenu ce programme :

    #include <iostream>
    #include <cmath>
    using namespace std;
    int n;
    int tester()
    {
       cin >> n;
       int tab[n][2];
       int graphe[n][n];
       for (int i = 0; i <n ; i++)
       {
          int x, y;
          cin >> x;
          cin >> y;
          tab[i][0] = x;
          tab[i][1] = y;
       }
       int comptes[n] = {0};
       int r;
       cin >> r;
       for (int i= 0; i <n; i++)
       {
          for (int j = 0; j <n; j++)
          {
             graphe[i][j] = sqrt((tab[i][0]-tab[j][0])*(tab[i][0]-tab[j][0]) + (tab[i][1]-tab[j][1])*(tab[i][1]-tab[j][1]));
          }
       }
    }
    int contaminer(distance, indice)
       {
          int nb = 0;
          for (int i = 0; i <n; i++)
          {
             if (int comptes[i] == 0 && int graphe[indice][i] <= distance)
             {
                int comptes[i] = 1;
                nb += 1 + contaminer(distance, i);
             }
          }
          return nb;
       }
    int main()
    {
       tester();
       for (int j = 0; j < n ; j++)
       {
          int distance;
          cin >> distance;
          int indice = 0;
          cout << contaminer(distance, indice) << endl;
       }
    }

    Hélas le compi m'indique

    source.cc: In function ‘int tester()’:
    source.cc:9:8: warning: variable ‘graphe’ set but not used [-Wunused-but-set-variable]
        int graphe[n][n];
            ^
    source.cc:18:8: warning: unused variable ‘comptes’ [-Wunused-variable]
        int comptes[n] = {0};
            ^
    source.cc: At global scope:
    source.cc:29:26: error: ‘indice’ was not declared in this scope
     int contaminer(distance, indice)
                              ^
    source.cc:29:32: error: expression list treated as compound expression in initializer [-fpermissive]
     int contaminer(distance, indice)
                                    ^
    source.cc:30:4: error: expected ‘,’ or ‘;’ before ‘{’ token
        {
        ^
    source.cc: In function ‘int tester()’:
    source.cc:28:1: warning: control reaches end of non-void function [-Wreturn-type]
     }
     ^

     Pouvez vous m'aider à trouver l'erreur ?

    Ca fait plusieurs jours que je cherche et je ne trouve définitivement pas ...

    Merci d'avance .

    • Partager sur Facebook
    • Partager sur Twitter
    Un random qui fait de l'algo
      15 avril 2018 à 11:26:23

      Tu dois préciser le type de tes paramètres de fonction, comme-ceci :

      int contaminer(int distance, int indice)

      Autres points :

      • Ta fonction tester doit retourner une valeur.
      • Evite les tableaux style C, préfère leur std::array ici (tableau dont la taille est connue à la compilation).
      • Les tableaux de tableaux sont lents, préfère un tableau 1D linérarisé.
      • N'utilises pas using namespace.

      -
      Edité par Nùménor 15 avril 2018 à 11:26:37

      • Partager sur Facebook
      • Partager sur Twitter
        15 avril 2018 à 11:59:35

        Tout d'abord merci beaucoup pour ta réponse .

        Ensuite,

        j'ai recodé mon programme en suivant tes indications et ça donne

        #include <iostream>
        #include <cmath>
        using namespace std;
        int n;
        int contaminer(int distance, int indice)
           {
              int nb = 0;
              for (int i = 0; i <n; i++)
              {
                 if (comptes[i] == 0 && graphe[indice][i] <= distance)
                 {
                    comptes[i] = 1;
                    nb += 1 + contaminer(distance, i);
                 }
              }
              return nb;
           }
        int main()
        {
           cin >> n;
           int tab[n][2];
           int graphe[n][n];
           for (int i = 0; i <n ; i++)
           {
              int x, y;
              cin >> x;
              cin >> y;
              tab[i][0] = x;
              tab[i][1] = y;
           }
           int comptes[n] = {0};
           int r;
           cin >> r;
           for (int i= 0; i <n; i++)
           {
              for (int j = 0; j <n; j++)
              {
                 graphe[i][j] = sqrt((tab[i][0]-tab[j][0])*(tab[i][0]-tab[j][0]) + (tab[i][1]-tab[j][1])*(tab[i][1]-tab[j][1]));
              }
           }
           for (int j = 0; j < n ; j++)
           {
              int distance;
              cin >> distance;
              int indice = 0;
              cout << contaminer(distance, indice) << endl;
           }
        }

        (je prefère supprimer tester() car au final on pouvait tout à fait s' en passer, je préfère utiliser using namespace car sinon les bugs sont encore moins compréhensibles et la lenteur des tableaux de tableaux ne me gêne pas )

        Mais le compi m'indique encore

        source.cc: In function ‘int contaminer(int, int)’:
        source.cc:10:14: error: ‘comptes’ was not declared in this scope
                  if (comptes[i] == 0 && graphe[indice][i] <= distance)
                      ^
        source.cc:10:33: error: ‘graphe’ was not declared in this scope
                  if (comptes[i] == 0 && graphe[indice][i] <= distance)
                                         ^
        source.cc: In function ‘int main()’:
        source.cc:31:8: warning: unused variable ‘comptes’ [-Wunused-variable]
            int comptes[n] = {0};
                ^

         Comment faire pour que comptes et graphe ne soient pas un problème ?



        -
        Edité par AlNonyme 15 avril 2018 à 12:00:30

        • Partager sur Facebook
        • Partager sur Twitter
        Un random qui fait de l'algo
          15 avril 2018 à 13:56:43

          > je préfère utiliser using namespace car sinon les bugs sont encore moins compréhensibles

          Si tu supprime le using namespace, il te faut remplacer cout par std::cout, cin par std::cin et sqrt par std::sqrt. Au vu de ton code, c'est les seules modifs que tu devrait avoir a réaliser (sauf si j'en ai manque)

          > et la lenteur des tableaux de tableaux ne me gêne pas

          C'est pas une question de lenteur, c'est une question de bonnes pratiques et de sécurité. utiliser des tableaux a la C comme ça peut créer des bugs (dont un dans ton code, j'y reviens)

          Pour tes erreurs, c'est simplement car compte et graphe n'existent pas dans ta fonction (logique vu qu'ils sont déclarés dans le main et que tu ne les passe pas a contaminer)

          Enfin, pour ce qui est du bug dont je parlais : int tab[n][2]; ceci est un VLA (variable length array) et c'est tout simplement pas supporte par le C++. Le code compile peut etre, mais tu n'as AUCUNNE garantie sur e fait qu'il fonctionnera. Mieux! De mémoire les VLA sont des undefined behavior ce qui veux dire que le programme a le droit de faire ce qu'il veux (même formater ton disque dur ou lancer une attaque nucléaire sur la Corée du nord). Si tu avais utilise std::array ton code n'aurait pas compile et tu aurais pu corriger.

          • Partager sur Facebook
          • Partager sur Twitter
            15 avril 2018 à 16:16:01

            Certes mais ce que je cherche à savoir c'est comment éviter

            source.cc:10:14: error: ‘comptes’ was not declared in this scope
                      if (comptes[i] == 0 && graphe[indice][i] <= distance)
                          ^
            source.cc:10:33: error: ‘graphe’ was not declared in this scope
                      if (comptes[i] == 0 && graphe[indice][i] <= distance)
                                             ^

             car c'est ce qui me contraint le plus :(

            (Même si ça m'embête que les VLA attaquent la Corée du Nord grâce à des missiles commandés par Open Classrooms)

            -
            Edité par AlNonyme 15 avril 2018 à 16:29:44

            • Partager sur Facebook
            • Partager sur Twitter
            Un random qui fait de l'algo
              15 avril 2018 à 16:53:41

              Salut

              Comme le dit le compilateur "comptes" et "graphes" ne sont pas déclarés dans ta fonction, ta fonction ne connait que les paramètres qu'elle reçoit (distance et indice).

              Voici une explication : http://guillaume.belz.free.fr/doku.php?id=fonctions#variable_locale_a_une_fonction

              Et un cours C++ qui lui est à jour que je te conseille ;) : http://guillaume.belz.free.fr/doku.php?id=programmez_avec_le_langage_c

              N’oublie pas les conseils des voisins au dessus comme using namespace std qui est une mauvaise pratique et qui risque de te causer tout autant d'ennui plus tard : http://guillaume.belz.free.fr/doku.php?id=hello_world#l_espace_de_nom_std

              -
              Edité par XxAnoth-ChaxX 15 avril 2018 à 16:58:01

              • Partager sur Facebook
              • Partager sur Twitter
                16 avril 2018 à 11:28:21

                Ok donc si je comprends bien je dois changer mon programme pour qu'il ressemble à un truc comme ça ?
                #include <iostream>
                #include <cmath>
                int n;
                int contaminer(int distance, int indice, array compte, array graphe)
                   {
                      int nb = 0;
                      for (int i = 0; i <n; i++)
                      {
                         if (comptes[i] == 0 && graphe[indice][i] <= distance)
                         {
                            comptes[i] = 1;
                            nb += 1 + contaminer(distance, i);
                         }
                      }
                      return nb;
                   }
                int main()
                {
                   std::cin >> n;
                   int tab[n][2];
                   int graphe[n][n];
                   for (int i = 0; i <n ; i++)
                   {
                      int x, y;
                      std::cin >> x;
                      std::cin >> y;
                      tab[i][0] = x;
                      tab[i][1] = y;
                   }
                   int comptes[n] = {0};
                   int r;
                   std::cin >> r;
                   for (int i= 0; i <n; i++)
                   {
                      for (int j = 0; j <n; j++)
                      {
                         graphe[i][j] = sqrt((tab[i][0]-tab[j][0])*(tab[i][0]-tab[j][0]) + (tab[i][1]-tab[j][1])*(tab[i][1]-tab[j][1]));
                      }
                   }
                   for (int j = 0; j < n ; j++)
                   {
                      int distance;
                      std::cin >> distance;
                      int indice = 0;
                      std::cout << contaminer(distance, indice, compte, graphe) << endl;
                   }
                }

                Le problème c'est que je ne sais pas comment mettre les tableaux compte et graphe comme arguments pour contaminer().

                Merci à tous pour vos réponses, j'en apprends beaucoup sur ce forum !

                -
                Edité par AlNonyme 16 avril 2018 à 11:29:13

                • Partager sur Facebook
                • Partager sur Twitter
                Un random qui fait de l'algo
                  16 avril 2018 à 13:11:51

                  Salut tout le monde,

                  AlNonyme a écrit:

                  Le problème c'est que je ne sais pas comment mettre les tableaux compte et graphe comme arguments pour contaminer().


                  alors pour répondre à ta question, nous allons analyser la situation :p(pour que tu n'oublie pas et pour avoir un peu de connaissance).

                  d'abord quand nous déclarons un tableau du style C et que tu souhaite l'envoyer à une fonction, tu écris ceci:

                  int tab[5]; // déclaration d'un tableau fixe 
                  
                  void fonction(int tab[], int taille) //déclaration d'une fonction qui attend deux paramètres dont le premier est un tableau fixe et le second c'est la taille du tableau passé en paramètre  
                  

                  alors depuis quelque temps la philosophie du C++ s'éloigne considérablement du C(surtout avec le C++ moderne), alors la bibliothèque de la STL nous propose un conteneur capable de jouer le rôle d'un tableau fixe(du genre C) et cet conteneur utilise des remplates(donc capable de contenir n'importe quel type d'élément), le conteneur se nomme " array " donc std::array:

                  std::array<T, size_t> tableau;

                  donc là tu as un tableau fixe dont:

                  • le T indique que tu peux utiliser n'importe quel type d'élément
                  • size_t: pour être bref c'est la taille de ton tableau 

                  donc si tu veux déclarer par exemple un tableau des int avec 2 cases mémoires, tu auras:

                  std::array<int,2>tableau;

                  pour le remplissage confère la donc :-°

                  alors pour envoyer un objet du type std::array comme argument à une fonction c'est simple, tu auras :

                  T fonction(std::array< T, size_t> tab); // désolé ici j'utilise un template car je ne sais pas ton type de retour :-)

                  Nota: Pense à inclure <array> et je crois que tu 'as compris ? si non les autres memebres du FORUM peuvent mieux t'expliquer plus que moi:D 


                  -
                  Edité par EL-jos 16 avril 2018 à 13:12:36

                  • 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 .

                    16 avril 2018 à 19:56:45

                    Merci beaucoup j'ai compris (et merci pour le cours sur le c++, très instructif :D)

                    Mais encore une erreur :

                    Erreur de compilation :

                    source.cc: In function ‘int contaminer(int, int, int*, int*)’:
                    source.cc:10:49: error: invalid types ‘int[int]’ for array subscript
                              if (comptes[i] == 0 && graphe[indice][i] <= distance)
                                                                     ^
                    source.cc: In function ‘int main()’:
                    source.cc:46:59: error: cannot convert ‘int (*)[n]’ to ‘int*’ for argument ‘3’ to ‘int contaminer(int, int, int*, int*)’
                           cout << contaminer(distance, indice, graphe, comptes) ;
                                                                               ^

                     (j'ai préféré les tableaux du style c mais je ne crois pas que ce soit ça qui fasse boguer le programme)

                    Merci!

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Un random qui fait de l'algo
                      16 avril 2018 à 23:18:31

                      Bah d'accord,

                      de ma part je serrai vraiment trop bref  :p,

                      alors Voici quelque erreur:

                      • Les lignes 8  et 9 le monsieur(compilateur) te fait comprendre que la taille de la variable " n " n'est pas constante(Par ce que la taille d'un tableau fixe doit être constante et s'est bien logique d'où le nom de tableau fixé ou tableau à taille constante) donc tu doit rendre " n " constante.
                      • à La ligne 29 le monsieur te fait comprendre que tu n'as pas précisé les types de tes arguments( sont ils des int ?, double ?, float ?...).
                      • à la Ligne 34 Le monsieur te fait comprendre qu'il ne comprend pas ce que tu cherche à faire; L'initialisation dans un " if " ou " switch " est introduit en C++17 donc tu dois mettre ton compilo à jour :D 
                      • Le monsieur te fait comprendre que "comptes " et" graphe " n'est pas déclarer soit initialiser dans " contaminer ".

                      Nota: 

                      • évite d'utiliser le " using namespace std "( source des conflits)
                      • l'utilisation de la variable globale est déconseillé 
                      • Je n'ai pas cité toute les erreurs
                      • Les autres membres peuvent t'éclaircir mieux que moi :-° 

                      -
                      Edité par EL-jos 16 avril 2018 à 23:22:07

                      • 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 .

                        16 avril 2018 à 23:47:28

                        > (j'ai préféré les tableaux du style c mais je ne crois pas que ce soit ça qui fasse boguer le programme)

                        C'est pourtant tes tableaux qui sont a la faute. Notamment car tu les passe mal a ta fonction (tu as un int[][] que tu passe comme un int[]). On t l'as dit eviter les tableau a la C, et de lineariser et tu refuse de nous ecouter... Tes 2 erreurs (plus le probable crash quan ton prog se lancera a cause du VLA) auraient ete evitees...

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Déboguer un programme

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown