OVH Cloud OVH Cloud

string et constructeur

23 réponses
Avatar
Nicolas Aunai
bonjour,


comment, dans la liste d'initialisation d'un constructeur, définir la
taille d'une variable string ?


existe-t-il un constructeur pour string qui prendrait la taille en
argument ? je n'en ai aps vu, de plus il semble que :

class A
{
public :
string s;
A();
}

A()
:s(5)
{

}

ne marche pas car le constructeur de string semble vouloir un char *.

j'ai une parade qui consiste a faire :

A()
:s(" ") //'taille' espace
{

}

mais ça sonne un peu "bidouille" a deux euros..

--
Nico,
http://astrosurf.com/nicoastro
messenger : nicolas_aunai@hotmail.com

10 réponses

1 2 3
Avatar
Michaël Monerau
Laurent DELEPINE wrote:
Michaël Monerau wrote:
// On prend un std::string avec les espaces en input std::string
sInput;

// voir pour cin.getline, je ne me souviens plus exactement // les
arguments...



plutot getline (istream&, string&, char), cin.getline utilisant un
char*.


OK.

std::string::iterator itFound; while ((itFound >> sInput.find_first_of (' ')) != sInput.npos) // un espace est
trouvé, on le supprime sInput.erase (itFound);

std::vector<bool> Result; std::transform (sInput.begin(),
sInput.end(), std::back_inserter<vector<bool>(Result),
BoolExtractor ());




Quitte a utiliser getline, pourquoi ne pas utiliser le manipulateur
ws pour virer les espace.


En effet, j'y ai pensé. Mais comme je ne l'ai jamais utilisé, je ne
voulais pas risquer de dire une chose fausse. Comme l'utiliserais-tu alors ?

Personnellement je suis du partisant du "laisser faire le compilateur
s'il sait le faire, en général il est plus doué que moi".


Euh... je ne vois pas de quoi tu veux parler. Où ai-je fait ça dans le
code que j'ai proposé ?

--
Michaël Monerau


Avatar
DINH Viêt Hoà

Pourquoi faire une telle chose ? L'intérêt de std::string (en
particulier) est justement de ne pas s'occuper de la taille du string et
de faire les opérations dessus, comme ça nous plaît. Ensuite, c'est lui
qui s'occupe de redimensionner tout ça en dynamique, lorsqu'il y en a
besoin...


C'est peut-être intéressant de temps en temps de savoir prévoir sa
taille afin que la classe string ne passe pas son temps à redimensionner
la chaîne , non ?

redimensionner la chaîne est souvent coûteux :
allocation + copie.

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Avatar
Michaël Monerau
DINH Viêt Hoà wrote:


Pourquoi faire une telle chose ? L'intérêt de std::string (en
particulier) est justement de ne pas s'occuper de la taille du string et
de faire les opérations dessus, comme ça nous plaît. Ensuite, c'est lui
qui s'occupe de redimensionner tout ça en dynamique, lorsqu'il y en a
besoin...



C'est peut-être intéressant de temps en temps de savoir prévoir sa
taille afin que la classe string ne passe pas son temps à redimensionner
la chaîne , non ?

redimensionner la chaîne est souvent coûteux :
allocation + copie.


Je pense que c'est une optimisation qui n'a lieu d'être que dans des
boucles très souvent exécutées... Et dans ce cas-là, je serais plutôt
pour une utilisation du 'reserve' du vector (en utilisant un
vector<char> si l'usage s'y prête). Je ne crois pas que std::string ne
présente de 'reserve', mais c'est à vérifier tout de même...

--
Michaël Monerau


Avatar
Nicolas Aunai
"Michaël Monerau" avait soumis l'idée :

arg, en effet... On pourrait te reprocher d'avoir demandé à quelqu'un
d'autre de faire le projet :(


beh pas vraiment étant donné que le projet (fait par binôme) est
soutenu a l'oral devant une machine... ça se voit tout de suite si
c'est nous qui l'avons fait ou pas.

j'ai cependant l'exemple de mon binome qui l'année dernière c'était
fait retirer des points pour avoir utilisé des pointeurs dans son code,
alors que les pointeurs n'étaient pas au programme de l'année !
(aberrant je sais...)


oki, voilà :

#include <algorithm>

class Extractor
{
public:
bool operator (char test)
{
if (test == '.') // un point => true
return true;

return false; // un croix ou autre chose => false
}
};



ok


//....

// On prend un std::string avec les espaces en input
std::string sInput;

// voir pour cin.getline, je ne me souviens plus exactement
// les arguments...



là je ne suis pas trop... pourquoi "cin.getline" ? pourquoi pas cin >>
sInput tout simplement ? bon ok je connais pas trop cin et ses
méthodes... pas plus que cout d'ailleurs


// il faut enlever les espaces du string, parce que le functor
// retournera false s'il trouve un espace ! Ce qui fausserait les index


un functor c'est un objet avec une redéfinition de l'opérateur '()',
quel est sont intérêt ici ?

std::string::iterator itFound;
while ((itFound = sInput.find_first_of (' ')) != sInput.npos)
// un espace est trouvé, on le supprime
sInput.erase (itFound);

std::vector<bool> Result;
std::transform (sInput.begin(), sInput.end(),
std::back_inserter<vector<bool>(Result), BoolExtractor ());


je comprends pas trop le functor en dernier paramètre de transform(),
je n'ai pas vu la création de l'objet 'BoolExtractor', est-ce un oubli
?

Et voilà ! tu te retrouves à la fin avec le vector Result qui contient
la suite de bool que tu voulais au départ. En effet, std::transform
applique le functor à tous les éléments de la liste que tu lui donnes
(ici sInput.begin()->sInput.end()), et il met les résultats à la fin de
Result (grâce au back_inserter).


ok, pas mal... :o)

Donc, ça serait comme ça que je le ferais moi :) Mais après, tu as
malheureusement des contraintes... dommage :(


j'peux te dire que dans l'absolu je m'en fout des contraintes, si un
prof est intelligent je vois pas pourquoi un étudiant serait sanctionné
pour avoir plus de connaissances que le cours. Et s'il est sanctionné
alors tant pis pour le prof, l'étudiant lui, aura au moins appris qqch.
le fait est qu'il faut tout de même *bien* maitriser les codes "hors
programme" pour les mettre dans son projet, sinon on est pas crédible,
d'où ma rétissance sur les functor et transform que je ne connais pas
bien.

--
Nico,
http://astrosurf.com/nicoastro
messenger :

Avatar
Laurent DELEPINE
Michaël Monerau wrote:
Nicolas Aunai wrote:


"Michaël Monerau" a présenté l'énoncé suivant :



J'en pense que tu devrais tout de même prendre la chaîne dans un
std::string. Puis tu fais une fonction qui supprime les espaces dans ta
chaîne après(tout simple, un s.find_first_of (' ') avec un
s.erase(...)). Je trouve ça plus propre ;)



ben je vois aussi que ça fait plus propre, le problème étant que tout ça
est pour un projet (de deug) et mon code utilise déjà des notions tout a
fait hors programme...



arg, en effet... On pourrait te reprocher d'avoir demandé à quelqu'un
d'autre de faire le projet :(


Ca transformerait tout
seul la chaîne (avec ou sans les espaces, selon tes envies, moi je
ferais avec) en un vector<bool>, ou ce que tu veux d'autre. Si tu veux,
je peux te faire un petit exemple si tu ne connais pas encore ;-)



bah je veux bien ouais c'est sympa, mais ça sera uniquement pour ma
culture perso je pense...



oki, voilà :

#include <algorithm>

class Extractor
{
public:
bool operator (char test)
{
if (test == '.') // un point => true
return true;

return false; // un croix ou autre chose => false
}
};

//....

// On prend un std::string avec les espaces en input
std::string sInput;

// voir pour cin.getline, je ne me souviens plus exactement
// les arguments...


plutot getline (istream&, string&, char), cin.getline utilisant un char*.

std::string::iterator itFound;
while ((itFound = sInput.find_first_of (' ')) != sInput.npos)
// un espace est trouvé, on le supprime
sInput.erase (itFound);

std::vector<bool> Result;
std::transform (sInput.begin(), sInput.end(),
std::back_inserter<vector<bool>(Result), BoolExtractor ());



Quitte a utiliser getline, pourquoi ne pas utiliser le manipulateur ws
pour virer les espace. Personnellement je suis du partisant du "laisser
faire le compilateur s'il sait le faire, en général il est plus doué que
moi".


A+

LD



Avatar
Luc Hermitte
=?ISO-8859-15?Q?Michaël_Monerau?= wrote in
news:s5lyb.29922$:

std::string::iterator itFound;
while ((itFound = sInput.find_first_of (' ')) != sInput.npos)
// un espace est trouvé, on le supprime
sInput.erase (itFound);


Le erase-remove ne marche pas ? Tant qu'à faire ...
sInput.erase(std::remove(sInput.begin(),sInput.end(),' '), sInput.end());

On peut imaginer aussi un transform_if, fils caché entre std::transform et
copy_if l'algo perdu, pour directement passer de la chaine récupérée (avec
espaces) au vecteur de booléens.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

Avatar
Benoit Rousseau
Michaël Monerau wrote:
DINH Viêt Hoà wrote:

C'est peut-être intéressant de temps en temps de savoir prévoir sa
taille afin que la classe string ne passe pas son temps à redimensionner
la chaîne , non ?

redimensionner la chaîne est souvent coûteux :
allocation + copie.



Je pense que c'est une optimisation qui n'a lieu d'être que dans des
boucles très souvent exécutées... Et dans ce cas-là, je serais plutôt
pour une utilisation du 'reserve' du vector (en utilisant un
vector<char> si l'usage s'y prête). Je ne crois pas que std::string ne
présente de 'reserve', mais c'est à vérifier tout de même...



Est ce que string::resize( size_type ) ne marche pas dans ce cas ?

Mais si il s'agit d'ajout de caractères en fin de chaines ( ce qui se
fait souvent dans une boucle), autant utiliser des stringstreams, non ?


--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/


Avatar
Michaël Monerau
Luc Hermitte wrote:
=?ISO-8859-15?Q?Michaël_Monerau?= wrote in
news:s5lyb.29922$:


std::string::iterator itFound;
while ((itFound = sInput.find_first_of (' ')) != sInput.npos)
// un espace est trouvé, on le supprime
sInput.erase (itFound);



Le erase-remove ne marche pas ? Tant qu'à faire ...
sInput.erase(std::remove(sInput.begin(),sInput.end(),' '), sInput.end());


Je ne connaissais pas ce 'remove' :(

On peut imaginer aussi un transform_if, fils caché entre std::transform et
copy_if l'algo perdu, pour directement passer de la chaine récupérée (avec
espaces) au vecteur de booléens.


En effet, je n'y avais pas pensé. Ce serait beaucoup plus pratique !

--
Michaël Monerau


Avatar
Michaël Monerau
Nicolas Aunai wrote:
"Michaël Monerau" avait soumis l'idée :

// On prend un std::string avec les espaces en input
std::string sInput;

// voir pour cin.getline, je ne me souviens plus exactement
// les arguments...



là je ne suis pas trop... pourquoi "cin.getline" ? pourquoi pas cin >>
sInput tout simplement ? bon ok je connais pas trop cin et ses
méthodes... pas plus que cout d'ailleurs


Si tu fais "cin >> sInput", tu n'auras les caractères que jusqu'au
prochain espace... A moins qu'on ne modifie le flag 'skipws' il me semble...

// il faut enlever les espaces du string, parce que le functor
// retournera false s'il trouve un espace ! Ce qui fausserait les index



un functor c'est un objet avec une redéfinition de l'opérateur '()',
quel est sont intérêt ici ?


Son intérêt est qu'il peut être utilisé très facilement. C'est un peu
une sémantique de fonction, qui autorise un traitement beaucoup plus
puissant. Ici, il est vrai qu'une fonction pourrait apparaître tout
aussi efficace. Ca peut cependant s'avérer plus rapide, car l'opérator
peut être 'inliner', et les performances peuvent en être améliorées...
Autrement, pour le principe global des functors, je ne pourrais pas tout
t'expliquer ici, ça prendrait trop de temps et j'en oublierais sûrement
:D mais tu peux tout de même regarder sur internet, tu trouveras de
bonnes explications. Le mieux reste quand même de consulter TC++PL si tu
l'as sous la main...

Enfin, pour info, ça permet des constructions plus génériques. Parce que
dans le functor, tu peux avoir des membres données... Dans mon exemple,
le constructeur ne prend aucun paramètre. Mais il pourrait prendre en
argument le caractère qui équivaut à true... Il sauvegarderait cette
donnée dans un membre privé, puis dans l'operator, il s'en reservirait
pour convertir en bool. C'est un petit exemple de l'utilité directe d'un
functor...

std::string::iterator itFound;
while ((itFound = sInput.find_first_of (' ')) != sInput.npos)
// un espace est trouvé, on le supprime
sInput.erase (itFound);

std::vector<bool> Result;
std::transform (sInput.begin(), sInput.end(),
std::back_inserter<vector<bool>(Result), BoolExtractor ());



je comprends pas trop le functor en dernier paramètre de transform(), je
n'ai pas vu la création de l'objet 'BoolExtractor', est-ce un oubli ?


En fait, il faut passer un objet functor. Et c'est ce que je fais en
créant un objet "BoolExtractor()" local. Le constructeur ne prend pas
d'argument, ce qui explique le '()'.

Donc, ça serait comme ça que je le ferais moi :) Mais après, tu as
malheureusement des contraintes... dommage :(



j'peux te dire que dans l'absolu je m'en fout des contraintes, si un
prof est intelligent je vois pas pourquoi un étudiant serait sanctionné
pour avoir plus de connaissances que le cours. Et s'il est sanctionné
alors tant pis pour le prof, l'étudiant lui, aura au moins appris qqch.
le fait est qu'il faut tout de même *bien* maitriser les codes "hors
programme" pour les mettre dans son projet, sinon on est pas crédible,
d'où ma rétissance sur les functor et transform que je ne connais pas bien.


C'est la théorie... Mais il suffit que l'interrogateur soit borné pour
remettre en cause cette vision intelligente, mais malheureusement pas
tout le temps vraie :'( Pour les functors, ça devient tout de suite plus
limpide quand tu lis un peu dessus ! Et c'est vraiment très pratique.

--
Michaël Monerau


Avatar
Laurent DELEPINE
Michaël Monerau wrote:

Quitte a utiliser getline, pourquoi ne pas utiliser le manipulateur
ws pour virer les espace.



En effet, j'y ai pensé. Mais comme je ne l'ai jamais utilisé, je ne
voulais pas risquer de dire une chose fausse. Comme l'utiliserais-tu alors ?


Ben flute alors. Moi qui esperait avoir un exemple d'utilisation sans
étaler mon inculture :-)

Après verification, il semble inadapté ici. Il permet d'enlever les
espaces en debut de ligne (plus exactement a partir de la position
courante du flux jusqu'au premier caractere non filtré).

Par contre ca m'a permis de decouvrir un site de reference du C++ :
http://www.cplusplus.com/

A+

LD


1 2 3