212 votes

L'équivalent C++ de StringBuffer/StringBuilder ?

Existe-t-il une classe de la bibliothèque de modèles standard C++ qui offre une fonctionnalité efficace de concaténation de chaînes de caractères, similaire à la classe C# StringBuilder ou de Java StringBuffer ?

3 votes

La réponse courte est : Oui, STL a une classe pour cela et c'est std::ostringstream .

0 votes

Salut @andrew. Pouvez-vous modifier la réponse acceptée ? Il y a une réponse gagnante claire et ce n'est pas la réponse acceptée actuellement.

1 votes

@null c'est fait !

184voto

jk. Points 8019

La méthode C++ consiste à utiliser std::stringstream ou simplement des concaténations de chaînes de caractères. Les chaînes C++ étant mutables, les considérations de performance de la concaténation sont moins importantes.

en ce qui concerne le formatage, vous pouvez effectuer le même formatage sur un flux, mais d'une manière différente, similaire à cout . ou vous pouvez utiliser un foncteur fortement typé qui encapsule ceci et fournit une interface de type String.Format, par exemple. boost::format

78 votes

Les chaînes de caractères C++ sont mutables : exactement. La raison entière StringBuilder existe est de couvrir l'inefficacité du type de base immuable String de Java . En d'autres termes StringBuilder est un patchwork, nous devrions donc être heureux de ne pas avoir besoin d'une telle classe en C++.

62 votes

@bobobobo les chaînes immuables ont d'autres avantages cependant, c'est un cheval de course.

8 votes

Les simples concaténations de chaînes de caractères ne créent-elles pas un nouvel objet, ce qui pose le même problème que l'immuabilité en Java ? Considérons que toutes les variables sont des chaînes de caractères dans l'exemple suivant : a = b + c + d + e + f ; Ne va-t-on pas appeler operator+ sur b et c, puis operator+ sur le résultat et d, etc.

108voto

Stu Points 241

Le site std::string.append n'est pas une bonne option car elle n'accepte pas de nombreux types de données. Une alternative plus utile est d'utiliser std::stringstream comme ça :

#include <sstream>
// ...

std::stringstream ss;

//put arbitrary formatted data into the stream
ss << 4.5 << ", " << 4 << " whatever";

//convert the stream buffer into a string
std::string str = ss.str();

55voto

iain Points 4876

NOTE : cette réponse a fait l'objet d'une certaine attention récemment. Je ne la préconise pas comme solution (c'est une solution que j'ai vue dans le passé, avant la STL). Il s'agit d'une approche intéressante qui ne devrait être appliquée qu'à partir de std::string ou std::stringstream si après avoir profilé votre code vous découvrez que cela apporte une amélioration.

J'utilise normalement soit std::string ou std::stringstream . Je n'ai jamais eu de problèmes avec ceux-ci. Normalement, je réserve d'abord un peu de place si je connais la taille approximative de la corde à l'avance.

J'ai vu d'autres personnes fabriquer leur propre constructeur de cordes optimisé dans un passé lointain.

class StringBuilder {
private:
    std::string main;
    std::string scratch;

    const std::string::size_type ScratchSize = 1024;  // or some other arbitrary number

public:
    StringBuilder & append(const std::string & str) {
        scratch.append(str);
        if (scratch.size() > ScratchSize) {
            main.append(scratch);
            scratch.resize(0);
        }
        return *this;
    }

    const std::string & str() {
        if (scratch.size() > 0) {
            main.append(scratch);
            scratch.resize(0);
        }
        return main;
    }
};

Il utilise deux cordes : une pour la majorité de la corde et l'autre comme zone de grattage pour concaténer des cordes courtes. Il optimise les ajouts en regroupant les opérations d'ajouts courts dans une petite chaîne, puis en l'ajoutant à la chaîne principale, ce qui réduit le nombre de réaffectations nécessaires sur la chaîne principale lorsqu'elle devient plus grande.

Je n'ai pas eu besoin de cette astuce avec std::string ou std::stringstream . Je pense que c'était utilisé avec une bibliothèque de chaînes de caractères tierce avant std::string, c'était il y a longtemps. Si vous adoptez une telle stratégie, commencez par profiler votre application.

14 votes

Réinventer la roue. std::stringstream est la bonne réponse. Voir les bonnes réponses ci-dessous.

13 votes

@Kobor42 Je suis d'accord avec vous comme je le souligne sur la première et la dernière ligne de ma réponse.

1 votes

Je ne pense pas que le scratch n'est pas vraiment utile ici. Le nombre de réaffectations de la chaîne principale sera en grande partie fonction de sa taille finale, et non du nombre d'opérations d'ajout, à moins que l'option string est vraiment pauvre (c'est-à-dire qu'elle n'utilise pas la croissance exponentielle). Ainsi, le fait de "regrouper" les append ne sert à rien car une fois que le sous-jacent string est grande, elle ne croîtra qu'occasionnellement dans un sens ou dans l'autre. En plus de cela, il ajoute un tas d'opérations de copie redondantes, et peut plus réaffectations (d'où les appels à new / delete ) puisque vous ajoutez à une chaîne courte.

46voto

dan04 Points 33306

std::string est l'équivalent C++ : il est mutable.

13voto

Andy Shellam Points 8120

Vous pouvez utiliser .append() pour simplement concaténer des chaînes de caractères.

std::string s = "string1";
s.append("string2");

Je pense que tu pourrais même être capable de le faire :

std::string s = "string1";
s += "string2";

Quant aux opérations de formatage de l'interface C# StringBuilder Je crois que snprintf (ou sprintf si vous voulez prendre le risque d'écrire un code bogué ;-) ) dans un tableau de caractères et le reconvertir en chaîne de caractères est à peu près la seule option.

0 votes

Pas de la même manière que printf ou String.Format de .NET, n'est-ce pas ?

1 votes

C'est un peu malhonnête de dire qu'ils sont la seule voie possible.

2 votes

@jk - c'est la seule façon de comparer la capacité de formatage du StringBuilder de .NET, ce qui est ce que la question originale demandait spécifiquement. J'ai dit "je crois" donc je peux me tromper, mais pouvez-vous me montrer un moyen d'obtenir la fonctionnalité de StringBuilder en C++ sans utiliser printf ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X