OVH Cloud OVH Cloud

Equivalent StringBuilder

17 réponses
Avatar
Delf
Bonsoir,

je cherche un équivalent de StringBuffer/StringBuilder mais en C++.

J'ai une chaîne que je créé par concaténation de nombreux caractères...
pas très performant...

Merci :)

--
Delf
Do not use this email in Cc!
Quand je vais aux chiottes, je prends un manuel CISCO.

10 réponses

1 2
Avatar
Sylvain
Delf wrote on 29/04/2006 23:22:
Bonsoir,

je cherche un équivalent de StringBuffer/StringBuilder mais en C++.

tu cherches une implémentation avec d'éventuelles contraintes

particulières (ascii 8bits et/ou UTFn et/ou ??) ou juste un nom comme
'ostringstream' ?

J'ai une chaîne que je créé par concaténation de nombreux caractères...
pas très performant...


tu peux déjà commencer par un type simplissime (sans reallocation, avec
taille fixe figée à la création) comme:

class String {
private:
char* internal;
size_t count, size;
public:
String(size_t max){
internal = new char[size = max + 1];
::memset(internal, 0, size);
count = 0;
}
~String(){
delete [] internal;
}

operator const char* () const {
return internal;
}

friend String& operator << (String& ioStr, char ch){
if (ioStr.count < ioStr.size)
ioStr.internal[ioStr.count++] = ch;
return ioStr;
}
};

Sylvain.

Avatar
Fabien LE LEZ
On Sat, 29 Apr 2006 23:22:57 +0200, Delf :

J'ai une chaîne que je créé par concaténation de nombreux caractères...
pas très performant...


Tu veux dire que tu as effectivement vérifié que std::string est trop
lent pour tes besoins ?
Si oui, et si tu as une estimation de la taille finale, tu peux
commencer par essayer en utilisant std::string::reserve().

Avatar
Jean-Marc Bourguet
Delf writes:

je cherche un équivalent de StringBuffer/StringBuilder mais en C++.

J'ai une chaîne que je créé par concaténation de nombreux caractères... pas
très performant...


ostringstream ?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Fabien LE LEZ
On 30 Apr 2006 09:53:45 +0200, Jean-Marc Bourguet :

J'ai une chaîne que je créé par concaténation de nombreux caractères... pas
très performant...


ostringstream ?


Pour rajouter des caractères, j'ai des doutes. Utiliser directement
std::string::append() n'est-il pas plus efficace ?


Avatar
Delf
Fabien LE LEZ wrote:

Pour rajouter des caractères, j'ai des doutes. Utiliser directement
std::string::append() n'est-il pas plus efficace ?


A vrai dire, je ne sais pas. En Java ou C#, quand je concatène des
caractères, je n'utilise jamais la classe String mais son équivalent.

Après, je n'ai jamais fait de tests de performance, je fais confiance
aux documentations.

--
Delf
Do not use this email in Cc!
Etant philosophe, j'ai un problème pour chaque solution.

Avatar
Delf
Fabien LE LEZ wrote:

Tu veux dire que tu as effectivement vérifié que std::string est trop
lent pour tes besoins ?


Non. Mais si je réalloue à chaque concaténation, je suis persuadé que
c'est pas le mieux à faire.

Si oui, et si tu as une estimation de la taille finale, tu peux
commencer par essayer en utilisant std::string::reserve().


J'avais pensé à utiliser reverse() mais je ne peux pas estimer la taille
finale.

--
Delf
Do not use this email in Cc!
L'alcool tue lentement. On s'en fout. On n'est pas pressé.

Avatar
Fabien LE LEZ
On Sun, 30 Apr 2006 11:53:58 +0200, Delf :

Tu veux dire que tu as effectivement vérifié que std::string est trop
lent pour tes besoins ?


Non.


Dans ce cas, fais-le.
Optimiser au hasard ne donne jamais rien de bon.

Mais si je réalloue à chaque concaténation,


Et pourquoi réallouerais-tu à chaque concaténation ?
Note que si tu utilises reserve() à bon escient, tu es assuré de
l'absence de réallocation.

Tu as besoin d'un type "chaîne de caractères". Le type par défaut en
C++ est std::string. C'est donc le premier à essayer.
À la rigueur, si tu n'es pas sûr de toi, tu peux faire un
typedef std::string Chaine;
pour pouvoir facilement changer le type a posteriori.

Crée puis compile le programme, et fais-le tourner.
S'il tourne assez vite, ton boulot est terminé.
S'il est trop lent, il te faut un profiler pour déterminer la cause de
cette lenteur. Elle n'est pas forcément où tu l'attends.


Avatar
Fabien LE LEZ
On Sun, 30 Apr 2006 11:52:07 +0200, Delf :

A vrai dire, je ne sais pas. En Java ou C#, quand je concatène des
caractères, je n'utilise jamais la classe String mais

son équivalent.


C'est quoi, "son équivalent" ?

Après, je n'ai jamais fait de tests de performance, je fais confiance
aux documentations.


Quelles documentations ?
Ça m'étonnerait que l'éditeur d'un compilateur C++ récent claironne
fièrement que son implémentation de std::string est pourrie...

Avatar
James Kanze
Delf wrote:

je cherche un équivalent de StringBuffer/StringBuilder mais en
C++.


J'ai une chaîne que je créé par concaténation de nombreux
caractères... pas très performant...


L'idée de base, en C++, c'est que std::string soit assez
performant pour ça. Si ce n'est pas le cas, essaie
std::vector<char>, avec une conversion au moyen de
std::string( v.begin(), v.end() ). Et si tu connais la taille
finale d'avance, n'hésite pas à te servir de
std::vector<>::reserve().

--
James Kanze
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

Avatar
James Kanze
Jean-Marc Bourguet wrote:
Delf writes:


je cherche un équivalent de StringBuffer/StringBuilder mais
en C++.



J'ai une chaîne que je créé par concaténation de nombreux
caractères... pas très performant...



ostringstream ?


Il a bien dit « pas très performant ». D'après ce que j'ai
entendu dire, ça pourrait s'appliquer encore plus à
ostringstream.

Dans la pratique :

std::vector< char > : garantit les performances des push_back ; il
garantit en plus que reserve ait un effet.

std::string : rien de garantit, et dans la pratique, il y a, ou
il y a bien eu, des implémentations où push_back prend un
temps O(n), où n est la taille de la chaîne (ce qui veut
dire que construire une chaîne de taille n de cette manière
est O(n^2)).

Dans une implémentation qui n'est pas trop mauvaise, reserve
doit avoir un effet (mais la norme permet de le traiter
comme un no-op). En faisant quelque chose du genre :
if ( buffer.size() == buffer.capacity() ) {
buffer.reserve( 2 * buffer.size() ) ;
}
avant chaque push_back, on doit dans la pratique atteindre
quelque chose qui s'approche aux performances de
std::vector< char >.

std::ostringstream : la norme ne dit absolument rien de ses
performances, qui sont souvent assez décévantes.

Personellement, si ce n'est que du caractère par caractère,
j'utiliserais std::string et push_back d'abord. Si ça s'avérait
trop lent, je le remplacerais avec std::vector< char > et
push_back, suivi d'un std::string( v.begin(), v.end() ) pour
convertir le résultat en chaîne.

--
James Kanze
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


1 2