Partage
  • Partager sur Facebook
  • Partager sur Twitter

no matching function for call to ‘frog::frog

Sujet résolu
    12 août 2018 à 0:09:57

    Bonjours a tous,

    Souhaitant m’entraîner a l'algorithmie en c++, je me suis donc rendu sur France ioi, mais ayant un peu beaucoup la flemme de me taper tous le niveau 1 et 2, je suis passer au déblocage du niveau 3

    J'en suis au problème des grenouille (je vais mettre l’énoncer a la fin) et voici mon code :

    #include <iostream>
    #include <vector>
    #include <string>
    
    struct frog
    {
    	int number = -1;
    	int time_first = 0;
    	int distance = 0;
    };
    
    bool operator!=(frog const& frog_1, frog const& frog_2)
    {
    	if(frog_1.number == frog_2.number)
    	{
    		return false;
    	}
    
    	return true;
    }
    
    struct round_report
    {
    	int frog_runner;
    	int distance;
    };
    
    std::vector<frog> create_frog_vector(int nb_frog)
    {
    	std::vector<frog> frogs;
    	for (int i{ 0 }; i < nb_frog; i++)
    	{
    		frogs.push_back( frog{ i+1, 0, 0 } );
    	}
    
    	return frogs;
    }
    
    round_report get_round_infos()
    {
    	int frog_runner;
    	std::cin >> frog_runner;
    
    	int distance;
    	std::cin >> distance;
    
    	return round_report{ frog_runner, distance };
    }
    
    bool has_equality(std::vector<frog> const& frogs, frog const& best_frog)
    {
    	for (auto const& frog : frogs)
    	{
    		if (best_frog != frog)
    		{
    			if (frog.distance == best_frog.distance)
    			{
    				return true;
    			}
    		}
    	}
    
    	return false;
    }
    
    void update_first(std::vector<frog> & frogs)
    {
    	frog best_frog;
    
    	for (int i{ 0 }; i < frogs.size(); i++)
    	{
    		if (frogs[i].distance > best_frog.distance)
    		{
    			best_frog = frogs[i];
    		}
    	}
    
    	if (best_frog.number != -1 && !has_equality(frogs, best_frog) )
    	{
    		frogs[best_frog.number - 1].time_first += 1;
    	}
    }
    
    void update_frogs(std::vector<frog> & frogs, round_report const& result)
    {
    	frogs[result.frog_runner - 1].distance += result.distance;
    }
    
    int get_first(std::vector<frog> & frogs)
    {
    	frog first;
    
    	for (auto const& runner : frogs)
    	{
    		if (runner.time_first > first.time_first)
    		{
    			first = runner;
    		}
    	}
    
    	return first.number;
    }
    
    int main()
    {
    	int nb_frog;
    	std::cin >> nb_frog;
    
    	int nb_round;
    	std::cin >> nb_round;
    
    	std::vector<frog> frogs{ create_frog_vector(nb_frog) };
    
    	for (int i{ 0 }; i < nb_round; i++)
    	{
    		update_first(frogs);
    		round_report result{ get_round_infos() };
    		update_frogs(frogs, result);
    	}
    
    	std::cout << get_first(frogs) << std::endl;;
    
    }
    

    Mon problème est plutôt simple : le code compile sous VS, pas sur France IoI, les erreurs donner :

    source.cc: In function ‘std::vector<frog> create_frog_vector(int)’:
    source.cc:33:40: error: no matching function for call to ‘frog::frog(<brace-enclosed initializer list>)’
           frogs.push_back( frog{ i+1, 0, 0 } );
                                            ^
    source.cc:33:40: note: candidates are:
    source.cc:5:8: note: constexpr frog::frog()
     struct frog
            ^
    source.cc:5:8: note:   candidate expects 0 arguments, 3 provided
    source.cc:5:8: note: constexpr frog::frog(const frog&)
    source.cc:5:8: note:   candidate expects 1 argument, 3 provided
    source.cc:5:8: note: constexpr frog::frog(frog&&)
    source.cc:5:8: note:   candidate expects 1 argument, 3 provided
    source.cc: In function ‘void update_first(std::vector<frog>&)’:
    source.cc:70:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
        for (int i{ 0 }; i < frogs.size(); i++)
                           ^
    source.cc: In function ‘int main()’:
    source.cc:117:46: error: cannot convert ‘round_report’ to ‘int’ in initialization
           round_report result{ get_round_infos() };
                                                  ^

    Je comprend bien (pour commencer la première erreur), il n'arrive pas a appeller le constructeur de frog avec les arguments donner, pourtant je donne bien les 3 arguments nécessaires (d’ailleurs 1 seul est réellement nécessaire, vu que les autre sont défini par défaut..)
    J'aimerais un peu d'aide pour m’éclairer la dessus..

    Merci d'avance pour votre aide / lecture

    HS sujet :

    nbGrenouilles numérotées de 1 à nbGrenouilles sont placées sur une ligne de départ. À chaque tour, on vous indique le numéro de la seule grenouille qui va sauter lors de ce tour, et la distance qu'elle va parcourir en direction de la ligne d'arrivée.
    
    Écrivez un programme qui détermine laquelle des grenouilles a été strictement en tête de la course au début du plus grand nombre de tours. Notez que comme on s'intéresse à qui est en tête au début de chaque tour, le bond du dernier tour ne sert à rien car même si la grenouille concernée passe en tête, la course est finie (il est purement honorifique selon la tradition algoréenne).



    -
    Edité par K4kugen 12 août 2018 à 0:10:58

    • Partager sur Facebook
    • Partager sur Twitter
      12 août 2018 à 0:42:11

      Salut

      Cette façon de faire n'est pas correcte (de ce que je crois), j'ai pas les connaissances pour t'expliquer pourquoi, toutefois pour ton erreur, il faut faire comme ça :

          std::vector<frog> frogs {};
          frog my_frog {};
      
          for (int i {0}; i < nb_frog; i++)
          {
              my_frog.number = i;
              my_frog.time_first = 0;
              my_frog.distance = 0;
      
              frogs.push_back(my_frog);
          }
      
          return frogs;

      Ligne 70 : Tu compares deux entiers différents, frogs.size() renvoi un type size_t et non int.

      -
      Edité par XxAnoth-ChaxX 12 août 2018 à 0:43:23

      • Partager sur Facebook
      • Partager sur Twitter
        12 août 2018 à 0:53:41

        Le problème ne vient pas de là.

        Le soucis se trouve a la ligne 33 comme l'indique le compilateur.
        Il faut savoir qu'en c++ une structure et une classe sont identique a un détail près : leur visibilité.
        Une classe est par defaut privée, tandis qu'une structure est publique.

        Tout ça pour en venir a ton problème, tu ne peux pas écrire :

        frogs.push_back( frog{ i+1, 0, 0 } );

        Pour faire ça, tu dois redéfinir le constructeur de ta structure (comme tu le ferais avec une classe).

        • Partager sur Facebook
        • Partager sur Twitter
          12 août 2018 à 2:33:04

          > Tout ça pour en venir a ton problème, tu ne peux pas écrire : > frogs.push_back( frog{ i+1, 0, 0 } );

          Depuis C++14 on peut le faire: https://en.cppreference.com/w/cpp/language/aggregate_initialization

          Le compilateur semble être configuré pour du C++11, il faudrait ajouter -std=c++14 (ou17) dans les options de compilation. Si ce n'est pas possible, il faut enlever les valeurs par défaut pour rendre le code compatible c++11.

          note:

          if(frog_1.number == frog_2.number)
              return false;
           return true;
          

          -> return frog_1.number != frog_2.number

          • pourquoi mélanger 2 types de boucle ? lignes 52 et 70

          -
          Edité par jo_link_noir 12 août 2018 à 2:34:05

          • Partager sur Facebook
          • Partager sur Twitter
            12 août 2018 à 13:13:56

            Je sais ce qu'est une structure, je n'en suis pas a ma première fois en C++, mais c'est sympa de me le rappeller

            Par contre, il faut savoir que ce code compile sous VS17 a jours, donc je doute que ne puisse pas faire cela, c'est le compilateur de France IOI qui n'est pas content

            Je ne savais pas que cette maniere de faire datait du c++14, et vu que ce n'est pas mon compilo, je vais devoir rendre ca compatible c++11

            Pour les notes jo_link_noir, ca va en effet etre modifier, merci pour tes remarques

            Merci a vous trois pour l'aide / le temps accordé

            -
            Edité par K4kugen 12 août 2018 à 13:15:09

            • Partager sur Facebook
            • Partager sur Twitter
              12 août 2018 à 16:07:42

              Salut,

              K4kugen a écrit:

              Je ne savais pas que cette maniere de faire datait du c++14, et vu que ce n'est pas mon compilo, je vais devoir rendre ca compatible c++11

              Le meilleur moyen est alors sans doute de rajouter un constructeur paramétré (et un constructeur par défaut, tant qu'à faire) à ta structure, sous une forme proche de
              struct frog
              {
                  frog():frog{-1,0,0}{
                  }
                  frog(int number, int first_time, int distance):
                      number{number}, first_time{first_time}, distance{distance}{
                  }
                  int number = -1;
                  int time_first = 0;
                  int distance = 0;
              };

              De cette manière, la partie de ton code qui pose problème (il y en aura peut-être d'autres :p ) sera au moins compatible avec C++11 et ultérieure, ce qui devrait satisfaire le compilateur de france IOI :D

              Dans le même ordre d'idée, je vois quelques adaptations possibles:

              Tu pars du principe que tu vas utiliser l'entrée standard dans la fonction get_round_info.  Mais, l'un dans l'autre, tu pourrais tout aussi bien envisager de créer un fichier texte qui contienne les informations pour "plusieurs dizaines de milliers" de frog, alors que l'introduction manuelle te limitera sans doute à seulement quelques dizaines :p

              Par chance, l'entrée standard et les fichiers standards sont touss les deux dérivés de std::istream, et on peut donc parfaitement fournir les deux à une fonction qui s'attend à recevoir une référence sur un std::istream comme paramètre.

              En modifiant ta fonction pour lui donner la forme de

              round_report get_round_infos(std::istream & ifs)
              {
                  int frog_runner;
                  ifs >> frog_runner;
               
                  int distance;
                  ifs >> distance;
               
                  return round_report{ frog_runner, distance };
              }

              tu pourrait l'utiliser aussi bien sous la forme de

              int main(){
                  std::vector<frog> tab;
                  /* récupère dix éléments depuis l'entrée standard */
                  for(size_t i=0; i<10; ++i){
                      tab.push_back( get_round_infos(std::cin) );
                  }
              }

              que sous la forme de

              int main(){
                  std::vector<frog> tab;
                  /* récupère tous les éléments contenus dans un fichier */
                  std::ifstream ifs("fichier.txt");
                  while(ifs){
                      tab.push_back(get_round_info(ifs));
                  }
              }

              Cela change très peu ta logique, finalement, mais cela t'offre beaucoup plus de souplesse quant à la manière de travailler ;)

              Enfin, lorsque tu t'attends à ce que l'utilisateur introduise une donnée, tu devrais au minimum:

              • afficher un message indiquant quelle donnée tu t'attends à ce qu'il introduise (et, le cas échéant, les limites que tu veux lui imposer)
              • t'assurer que la donnée introduite correspond (en type de donnée et en valeur, s'il y a des limites imposées) à ce que tu attends.

              L'idéal étant de boucler sur l'affichage du message et la récupération de la donnée aussi longtemps que l'information n'est pas "correcte".

              Il en va de même (à ceci près qu'il n'y a pas de message à afficher) lorsque tu souhaite extraire une donnée d'un fichier texte, l'idéal étant alors de lancer une exception si la donnée ne correspond pas à ce que tu attends, pour éviter que ton application ne se retrouve dans un état "invalide" ;)

              • 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
                12 août 2018 à 23:48:20

                Tout d'abord, merci a toi pour tous tes conseils, je note ça pour la prochaine fois

                C'est vrai que j'ai zapper complètement toutes ces parties (principalement la partie "affichage de ce qui est attendu" et "vérification des entrée") car le programme est destiné a être utilisé par un ordinateur (ce qui n'excuse pas mon oublie), et il me semblais avoir lu que les test de france ioi ne concernait pas une fausse entrée.

                Plutôt pour la partie souplesse de mon code (que je garde en note, c'est une manière de voir que je n'ai pas encore), je peux expliquer cela par l'utilisation de ce programme unique, les demandes ne vont pas évoluées, et le programme sera supprimé des que les tests seront passés.

                N'y vois aucune mauvaise foi, je tente juste de justifier mes mauvais choix, et je profite de tes conseils pour m’améliorer, encore merci

                • Partager sur Facebook
                • Partager sur Twitter

                no matching function for call to ‘frog::frog

                × 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