J'ai un vector<int>
conteneur qui a des entiers (par exemple {1,2,3,4}) et je voudrais convertir en une chaîne de la forme
"1,2,3,4"
Quelle est la manière la plus propre de faire cela en C ++? En Python, voici comment je le ferais:
>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'
Réponses:
Certainement pas aussi élégant que Python, mais rien n'est aussi élégant que Python en C ++.
Vous pouvez utiliser un
stringstream
...Vous pouvez également utiliser à la
std::for_each
place.la source
std::string s = ss.str()
. Si vous voulez unconst char*
, utilisezs.c_str()
. (Notez que, bien que syntaxiquement correct,ss.str().c_str()
vous donnera unconst char*
qui pointe vers un temporaire qui cessera d'exister à la fin de l'expression complète. Cela fait mal.)#include <sstream>
En utilisant std :: for_each et lambda, vous pouvez faire quelque chose d'intéressant.
Voir cette question pour un petit cours que j'ai écrit. Cela n'imprimera pas la virgule de fin. Aussi, si nous supposons que C ++ 14 continuera à nous donner des équivalents basés sur des plages d'algorithmes comme celui-ci:
la source
Vous pouvez utiliser std :: accumulate. Prenons l'exemple suivant
la source
','
devrait être","
string
classe a une surcharge pour l'+
opérateur qui peut également accepter des caractères. Alors','
c'est très bien.Une autre alternative est l'utilisation de
std::copy
et de laostream_iterator
classe:Pas aussi bien que Python. Pour cela, j'ai créé une
join
fonction:Ensuite, utilisé comme ceci:
Vous pourriez vous demander pourquoi je suis passé dans les itérateurs. Eh bien, en fait, je voulais inverser le tableau, alors je l'ai utilisé comme ceci:
Idéalement, je voudrais créer un modèle au point où il peut déduire le type char et utiliser des flux de chaînes, mais je ne pouvais pas encore le comprendre.
la source
join
fonction peut également être utilisée avec des vecteurs? Pouvez-vous donner un exemple, je suis nouveau en C ++.Avec Boost et C ++ 11, cela pourrait être réalisé comme ceci:
Enfin presque. Voici l'exemple complet:
Crédit au prétorien .
Vous pouvez gérer n'importe quel type de valeur comme ceci:
la source
Ceci est juste une tentative de résoudre l'énigme donnée par la remarque de 1800 INFORMATION sur sa deuxième solution manquant de généricité, pas une tentative de répondre à la question:
Fonctionne sur ma machine (TM).
la source
operator<<
surchargé). Bien sûr, un type sansoperator<<
peut provoquer des messages d'erreur très déroutants.join(v.begin(), v.end(), ",")
. La déduction d'argument de modèle ne produit pas le bon résultat si l'sep
argument est une chaîne littérale. Ma tentative de solution à ce problème . Fournit également une surcharge basée sur la plage plus moderne.Beaucoup de modèles / idées. Le mien n'est pas aussi générique ou efficace, mais j'ai juste eu le même problème et je voulais ajouter cela au mix comme quelque chose de court et de doux. Il gagne sur le plus petit nombre de lignes ... :)
la source
substr(...)
, utilisezpop_back()
pour supprimer le dernier caractère, devient alors beaucoup plus clair et propre.Si vous voulez faire
std::cout << join(myVector, ",") << std::endl;
, vous pouvez faire quelque chose comme:Notez que cette solution effectue la jointure directement dans le flux de sortie plutôt que de créer un tampon secondaire et fonctionnera avec tous les types qui ont un opérateur << sur un ostream.
Cela fonctionne également en cas d'
boost::algorithm::join()
échec, lorsque vous avez unvector<char*>
fichier au lieu d'unvector<string>
.la source
la source
std::stringstream
pour les grands tableaux carstringstream
sera capable d'allouer de la mémoire de manière optimiste, conduisant à des performances O (n.log (n)) au lieu de O (n²) pour un tableau de taillen
pour cette réponse. Peut égalementstringstream
ne pas créer de chaînes temporaires pourto_string(i)
.J'aime la réponse de 1800. Cependant, je déplacerais la première itération hors de la boucle car le résultat de l'instruction if ne change qu'une fois après la première itération
Cela peut bien sûr être réduit à moins d'instructions si vous le souhaitez:
la source
++i
sauf là où ils en avaient vraiment besoin,i++
car c'était la seule façon pour eux de ne pas oublier cela quand cela faisait une différence. (C'était la même chose avec moi, BTW.) Ils avaient déjà appris Java, où toutes sortes de C-ismes sont en vogue et cela leur a pris quelques mois (1 conférence + travail de laboratoire par semaine), mais à la fin la plupart des ils ont appris l'habitude d'utiliser le pré-incrément.Il existe des tentatives intéressantes pour apporter une solution élégante au problème. J'ai eu l'idée d'utiliser des flux basés sur des modèles pour répondre efficacement au dilemme initial du PO. Bien qu'il s'agisse d'un ancien article, j'espère que les futurs utilisateurs qui tomberont dessus trouveront ma solution bénéfique.
Premièrement, certaines réponses (y compris la réponse acceptée) ne favorisent pas la réutilisation. Puisque C ++ ne fournit pas une manière élégante de joindre des chaînes dans la bibliothèque standard (que j'ai vue), il devient important d'en créer une qui soit flexible et réutilisable. Voici ma chance:
Maintenant, pour l'utiliser, vous pouvez simplement faire quelque chose comme ce qui suit:
Notez comment l'utilisation de flux rend cette solution incroyablement flexible car nous pouvons stocker notre résultat dans un flux de chaînes pour le récupérer plus tard, ou nous pouvons écrire directement dans la sortie standard, un fichier, ou même sur une connexion réseau implémentée sous forme de flux. Le type imprimé doit simplement être itérable et compatible avec le flux source. STL fournit divers flux compatibles avec une large gamme de types. Donc tu pourrais vraiment aller en ville avec ça. Du haut de ma tête, votre vecteur peut être int, float, double, string, unsigned int, SomeObject *, etc.
la source
J'ai créé un fichier d'en-tête d'assistance pour ajouter une prise en charge de jointure étendue.
Ajoutez simplement le code ci-dessous à votre fichier d'en-tête général et incluez-le si nécessaire.
Exemples d'utilisation:
Le code derrière la scène:
la source
Voici une solution générique C ++ 11 qui vous permettra de faire
Le code est:
la source
Voici un moyen simple et pratique de convertir des éléments de a
vector
en astring
:Vous devez
#include <sstream>
pourostringstream
.la source
Expansion lors de la tentative de @sbi sur une solution générique qui n'est pas limitée à
std::vector<int>
ou à un type de chaîne de retour spécifique. Le code présenté ci-dessous peut être utilisé comme ceci:Dans le code d'origine, la déduction d'argument de modèle ne fonctionne pas pour produire le bon type de chaîne de retour si le séparateur est une chaîne littérale (comme dans les exemples ci-dessus). Dans ce cas, les typedefs comme
Str::value_type
dans le corps de la fonction sont incorrects. Le code suppose queStr
c'est toujours un type commestd::basic_string
, donc il échoue évidemment pour les chaînes littérales.Pour résoudre ce problème, le code suivant tente de déduire uniquement le caractère type de de l'argument de séparation et l'utilise pour produire un type de chaîne de retour par défaut. Ceci est réalisé en utilisant
boost::range_value
, qui extrait le type d'élément du type de plage donné .Maintenant, nous pouvons facilement fournir une surcharge basée sur la plage qui transmet simplement à la surcharge basée sur l'itérateur:
Démo en direct à Coliru
la source
comme l'a fait @capone,
Ensuite, nous pouvons appeler comme suit:
tout comme python:
la source
J'utilise quelque chose comme ça
la source
J'ai commencé avec la réponse de @ sbi, mais la plupart du temps, j'ai fini par envoyer la chaîne résultante à un flux, ce qui a créé la solution ci-dessous qui peut être transférée vers un flux sans avoir à créer la chaîne complète en mémoire.
Il est utilisé comme suit:
Où string_join.h est:
la source
J'ai écrit le code suivant. Il est basé sur C # string.join. Il fonctionne avec std :: string et std :: wstring et de nombreux types de vecteurs. (exemples dans les commentaires)
Appelez ça comme ça:
Code:
la source
Voici un moyen simple de convertir un vecteur d'entiers en chaînes.
la source
rejoindre en utilisant la fonction de modèle
J'ai utilisé un
template
function
pour joindre lesvector
éléments et j'ai supprimé l'if
instruction inutile en parcourant uniquement le premier à l'avant-dernier élément duvector
, puis en joignant le dernier élément après lafor
boucle. Cela évite également le besoin de code supplémentaire pour supprimer le séparateur supplémentaire à la fin de la chaîne jointe. Donc, pas deif
déclarations ralentissant l'itération et pas de séparateur superflu à ranger.Cela produit un appel de fonction élégante à se joindre à un
vector
desstring
,integer
oudouble
, etc.J'ai écrit deux versions: l'une renvoie une chaîne; l'autre écrit directement dans un flux.
Production
la source