|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 (permalink) |
|
Messages: n/a
Hébergeur: |
Bonjour à tous.
Je recois en paramètre d'une classe une chaîne qui contient plusieurs valeurs (des ints pour être précis). Dans mon constructeur, je récupère ces variables via des *stringstream. Jusque lÃ, pas de problème. La difficulté vient du fait que je souhaite ensuite affecter les valeurs obtenues à des variables constantes car les valeurs récupérées sont les valeurs que doivent avoir les variables constantes. Je ne peux donc pas donner de valeurs aux constantes dans la liste d'initialisation puisque les valeurs ne sont pas encore connues. Une idée ? Merci. |
|
|
|
#2 (permalink) |
|
Messages: n/a
Hébergeur: |
On Sat, 12 Apr 2008 14:52:10 +0200, David Côme <davidcome@wanadoo.fr>:
>Je ne peux donc pas donner de valeurs aux constantes dans la liste >d'initialisation puisque les valeurs ne sont pas encore connues. class C { public: C (std::string const&); private: int const a; int const b; }; C::C (std::string const& param) : a (GetParametre (param, 1)) , b (GetParametre (param, 2)) {} Où GetParametre (string const&, unsigned int n) est bien sûr une fonction qui découpe la chaîne et renvoie le n-ième entier. |
|
|
|
#3 (permalink) |
|
Messages: n/a
Hébergeur: |
On Sat, 12 Apr 2008 14:53:51 +0200, Fabien LE LEZ <gramster@gramster.com>
wrote: > On Sat, 12 Apr 2008 14:52:10 +0200, David Côme <davidcome@wanadoo.fr>: > >> Je ne peux donc pas donner de valeurs aux constantes dans la liste >> d'initialisation puisque les valeurs ne sont pas encore connues. > > class C > { > public: > C (std::string const&); > private: > int const a; > int const b; > }; > > C::C (std::string const& param) > : a (GetParametre (param, 1)) > , b (GetParametre (param, 2)) > {} > > > Où > GetParametre (string const&, unsigned int n) > est bien sûr une fonction qui découpe la chaîne et renvoie le n-ième > entier. > Ok, merci. |
|
|
|
#4 (permalink) |
|
Messages: n/a
Hébergeur: |
On 12 avr, 14:52, David Côme <davidc...@wanadoo.fr> wrote:
> Je recois en paramètre d'une classe une chaîne qui contient > plusieurs valeurs (des ints pour être précis). Dans mon > constructeur, je récupère ces variables via des *stringstream. > Jusque là, pas de problème. > La difficulté vient du fait que je souhaite ensuite affecter > les valeurs obtenues à des variables constantes car les > valeurs récupérées sont les valeurs que doivent avoir les > variables constantes. > Je ne peux donc pas donner de valeurs aux constantes dans la > liste d'initialisation puisque les valeurs ne sont pas encore > connues. > Une idée ? Fabien a montré la solution classique, mais il faut signaler que s'il s'agit de plusieurs valeurs, dans une seule chaîne de caractères, la solution est loin d'être optimale, parce qu'il faudrait récréer la istringstream pour chaque valeur, sautant les valeurs qu'on ne recherche pas chaque fois. Dans ces cas-ci, je me démande si le const vaut la peine. Const est surtout utile au niveau des arguments d'une fonction ou des variables globales (à cause des garanties qu'il promet), ou sinon quand il s'agit d'une expression integrale constante (parce que certaines constructions dans le langage l'exige). Ici, il s'agit uniquement à des variables qui ne sont de toute façon pas accessibles aux autres, et qui ne peuvent pas non plus servir dans des expressions const. Du coup, le const se résume à une petite promesse à toi-même. Dans la pratique, je n'utilise pour ainsi dire jamais const sur des variables locales ou membres privés. -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#5 (permalink) |
|
Messages: n/a
Hébergeur: |
James Kanze <james.kanze@gmail.com> writes:
> Fabien a montré la solution classique, mais il faut signaler que > s'il s'agit de plusieurs valeurs, dans une seule chaîne de > caractères, la solution est loin d'être optimale, parce qu'il > faudrait récréer la istringstream pour chaque valeur, sautant > les valeurs qu'on ne recherche pas chaque fois. Quel manque d'imagination! #include <ciso646> #include <map> #include <string> #include <vector> #include <sstream> #include <iostream> #include <iterator> #include <exception> class Error:public std::exception { std::string message; public: Error(std::string const& aMessage):message(aMessage){}; ~Error(void)throw(){}; const char* what(void){return(message.c_str());} }; class C { public: C(std::string const&); inline int getA(void) const {return a;} inline int getB(void) const {return b;} private: int const a; int const b; int getParameter(std::string const& arguments,unsigned int n); }; C::C(std::string const& param) : a(getParameter(param,1)), b(getParameter(param,2)) {} int C::getParameter(std::string const& arguments,unsigned int n){ typedef std::map<std::string,std::vector<int> > ParameterCache; static ParameterCache cache; ParameterCache::iterator parameters=cache.find(arguments); if(parameters==cache.end()){ std::istringstream in(arguments); std::vector<int> parsedArgs; while(not(in.eof())){ int argument; in>>argument; parsedArgs.push_back(argument); } cache[arguments]=parsedArgs; parameters=cache.find(arguments); } if(parameters->second.size()<=n){ throw Error("Too few arguments"); } return(parameters->second[n]); } int main(void){ C c0("0 1 2 3"); C c1("10 11 12 13"); std::cout<<"c0: "<<c0.getA()<<" "<<c0.getB()<<std::endl; std::cout<<"c1: "<<c1.getA()<<" "<<c1.getB()<<std::endl; return(0); } /* -*- mode: compilation; default-directory: "~/src/miscellaneous/tests-c++/" -*- Compilation started at Sun Apr 13 15:38:52 g++ -o const-member const-member.c++ && ./const-member c0: 1 2 c1: 11 12 Compilation finished at Sun Apr 13 15:38:57 */ -- __Pascal Bourguignon__ http://www.informatimago.com/ NEW GRAND UNIFIED THEORY DISCLAIMER: The manufacturer may technically be entitled to claim that this product is ten-dimensional. However, the consumer is reminded that this confers no legal rights above and beyond those applicable to three-dimensional objects, since the seven new dimensions are "rolled up" into such a small "area" that they cannot be detected. |
|
|
|
#6 (permalink) |
|
Messages: n/a
Hébergeur: |
On 13 avr, 15:39, Pascal Bourguignon <p...@informatimago.com> wrote:
> James Kanze <james.ka...@gmail.com> writes: > > Fabien a montré la solution classique, mais il faut signaler que > > s'il s'agit de plusieurs valeurs, dans une seule chaîne de > > caractères, la solution est loin d'être optimale, parce qu'il > > faudrait récréer la istringstream pour chaque valeur, sautant > > les valeurs qu'on ne recherche pas chaque fois. > Quel manque d'imagination! Tu as oublié l'émoticon:-). > class C > { > public: > C(std::string const&); > inline int getA(void) const {return a;} > inline int getB(void) const {return b;} > private: > int const a; > int const b; > int getParameter(std::string const& arguments,unsigned int n); > }; > C::C(std::string const& param) > : a(getParameter(param,1)), > b(getParameter(param,2)) > {} > int C::getParameter(std::string const& arguments,unsigned int n){ > typedef std::map<std::string,std::vector<int> > ParameterCache; > static ParameterCache cache; > ParameterCache::iterator parameters=cache.find(arguments); > if(parameters==cache.end()){ > std::istringstream in(arguments); > std::vector<int> parsedArgs; > while(not(in.eof())){ (Je sais que ta proposition est ironique, mais je tiens à signaler en passant quand même qu'avec ce test, tu risques de traiter un paramètre en trop, avec un comportement indéfini.) > int argument; > in>>argument; > parsedArgs.push_back(argument); > } > cache[arguments]=parsedArgs; > parameters=cache.find(arguments); > } > if(parameters->second.size()<=n){ > throw Error("Too few arguments"); > } > return(parameters->second[n]); > } Avec une gestion d'erreurs correcte, des locks en plus si le code est multi-thread, et assez de mémoire, effectivement, cette solution pourrait marcher. Mais j'ai quand même comme une impression que cette dernière considération va jouer contre elle la plupart du temps. > int main(void){ > C c0("0 1 2 3"); > C c1("10 11 12 13"); Tu aurais dû essayer: C c3( "1\n" ) ; Qui doit, je crois, provoque une erreur (mais qui ne le fait probablement pas). > std::cout<<"c0: "<<c0.getA()<<" "<<c0.getB()<<std::endl; > std::cout<<"c1: "<<c1.getA()<<" "<<c1.getB()<<std::endl; > return(0); > } > /* > -*- mode: compilation; default-directory: "~/src/miscellaneous/tests-c++/"-*- > Compilation started at Sun Apr 13 15:38:52 > g++ -o const-member const-member.c++ && ./const-member > c0: 1 2 > c1: 11 12 > Compilation finished at Sun Apr 13 15:38:57 > */ Et maintenant, avec une boucle : std::string line ; while ( std::getline( std::cin, line ) ) { C c( line ) ; std::cout << getA() << ' ' << c.getB() << std::endl ; } Avec en entrée, un fichier avec des milliards de lignes différentes. On pourrait imaginer quelque chose de ce genre, avec, disons : class C { static std::istringstream parser ; C( std::string const& init ) : a( getFirst( init ) ) , b( getNext() ) { parser >> std::ws ; if ( ! parser || parser.get() != EOF ) { throw uneErrorDeSyntax ; } } static int getFirst( std::string const& init ) { parser.str( init ) ; int result ; init >> result ; return result ; } static int getNext() { int result ; init >> result ; return result ; } // ... } ; C'est quand même assez fragile (puisqu'il dépend de l'ordre des initialisations), et évidemment, dès qu'il y a des threads... (On peut aussi le rendre thread-safe, mais c'est encore plus exotique.) -- James Kanze (GABI Software) email:james.kanze@gmail.com Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 |
|
|
|
#7 (permalink) |
|
Messages: n/a
Hébergeur: |
On Sun, 13 Apr 2008 15:39:49 +0200, Pascal Bourguignon
<pjb@informatimago.com> wrote: > James Kanze <james.kanze@gmail.com> writes: >> Fabien a montré la solution classique, mais il faut signaler que >> s'il s'agit de plusieurs valeurs, dans une seule chaîne de >> caractères, la solution est loin d'être optimale, parce qu'il >> faudrait récréer la istringstream pour chaque valeur, sautant >> les valeurs qu'on ne recherche pas chaque fois. > > Quel manque d'imagination! > > #include <ciso646> > #include <map> > #include <string> > #include <vector> > #include <sstream> > #include <iostream> > #include <iterator> > #include <exception> > > class Error:public std::exception { > std::string message; > public: > Error(std::string const& aMessage):message(aMessage){}; > ~Error(void)throw(){}; > const char* what(void){return(message.c_str());} > }; > > class C > { > public: > C(std::string const&); > inline int getA(void) const {return a;} > inline int getB(void) const {return b;} > private: > int const a; > int const b; > int getParameter(std::string const& arguments,unsigned int n); > }; > > C::C(std::string const& param) > : a(getParameter(param,1)), > b(getParameter(param,2)) > {} > > > int C::getParameter(std::string const& arguments,unsigned int n){ > typedef std::map<std::string,std::vector<int> > ParameterCache; > static ParameterCache cache; > ParameterCache::iterator parameters=cache.find(arguments); > if(parameters==cache.end()){ > std::istringstream in(arguments); > std::vector<int> parsedArgs; > while(not(in.eof())){ > int argument; > in>>argument; > parsedArgs.push_back(argument); > } > cache[arguments]=parsedArgs; > parameters=cache.find(arguments); > } > if(parameters->second.size()<=n){ > throw Error("Too few arguments"); > } > return(parameters->second[n]); > } > > int main(void){ > C c0("0 1 2 3"); > C c1("10 11 12 13"); > std::cout<<"c0: "<<c0.getA()<<" "<<c0.getB()<<std::endl; > std::cout<<"c1: "<<c1.getA()<<" "<<c1.getB()<<std::endl; > return(0); > } > > /* > -*- mode: compilation; default-directory: > "~/src/miscellaneous/tests-c++/" -*- > Compilation started at Sun Apr 13 15:38:52 > > g++ -o const-member const-member.c++ && ./const-member > c0: 1 2 > c1: 11 12 > > Compilation finished at Sun Apr 13 15:38:57 > */ > > C'est une très belle solution mais après réflexion , j'ai l'impression que je sort un tank pour écraser 2 mouches. |
|
|
|
#8 (permalink) |
|
Messages: n/a
Hébergeur: |
Le 13/04/2008 16:31, David Côme a écrit :
> > C'est une très belle solution mais après réflexion, j'ai l'impression que > je sors un tank pour écraser 2 mouches. J'aime bien le « après réflexion ». ;-) |
|
![]() |
| Outils de la discussion | |
|
|