Ich habe einen vector<int>
Container mit ganzen Zahlen (z. B. {1,2,3,4}) und möchte in eine Zeichenfolge des Formulars konvertieren
"1,2,3,4"
Was ist der sauberste Weg, dies in C ++ zu tun? In Python würde ich das so machen:
>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'
Antworten:
Auf jeden Fall nicht so elegant wie Python, aber nichts ist so elegant wie Python in C ++.
Sie könnten eine
stringstream
...Sie können
std::for_each
stattdessen auch verwenden.quelle
std::string s = ss.str()
. Wenn Sie eine möchtenconst char*
, verwenden Sies.c_str()
. (Beachten Sie, dass Sie, obwohl syntaktisch korrekt,ss.str().c_str()
einenconst char*
Hinweis erhalten, der auf ein temporäres#include <sstream>
Mit std :: for_each und lambda können Sie etwas Interessantes tun.
Siehe diese Frage für eine kleine Klasse, die ich geschrieben habe. Dadurch wird das nachfolgende Komma nicht gedruckt. Auch wenn wir davon ausgehen, dass C ++ 14 uns weiterhin bereichsbasierte Äquivalente von Algorithmen wie diesen liefert:
quelle
Sie können std :: accumulate verwenden. Betrachten Sie das folgende Beispiel
quelle
','
sollte sein","
string
Klasse hat eine Überladung für+
Operatoren, die auch Zeichen akzeptieren können. Also','
ist alles in Ordnung.Eine andere Alternative ist die Verwendung von
std::copy
und dieostream_iterator
Klasse:Auch nicht so schön wie Python. Zu diesem Zweck habe ich eine
join
Funktion erstellt:Dann benutzte es so:
Sie könnten fragen, warum ich die Iteratoren bestanden habe. Nun, eigentlich wollte ich das Array umkehren, also habe ich es so verwendet:
Im Idealfall möchte ich eine Vorlage erstellen, die auf den Char-Typ schließen lässt, und String-Streams verwenden, aber das konnte ich noch nicht herausfinden.
quelle
join
Funktion kann auch mit Vektoren verwendet werden? Bitte geben Sie ein Beispiel, ich bin neu in C ++.Mit Boost und C ++ 11 könnte dies folgendermaßen erreicht werden:
Naja fast. Hier ist das vollständige Beispiel:
Gutschrift an Prätorianer .
Sie können jeden Werttyp wie folgt behandeln:
quelle
Dies ist nur ein Versuch, das Rätsel zu lösen, das sich aus der Bemerkung von 1800 INFORMATION zu seiner zweiten Lösung ohne Generizität ergibt, und kein Versuch, die Frage zu beantworten:
Funktioniert auf meinem Computer (TM).
quelle
operator<<
überladen wurde). Natürlich kann ein Typ ohneoperator<<
sehr verwirrende Fehlermeldungen verursachen.join(v.begin(), v.end(), ",")
. Der Abzug von Vorlagenargumenten führt nicht zum richtigen Ergebnis, wenn dassep
Argument ein Zeichenfolgenliteral ist. Mein Versuch, eine Lösung für dieses Problem zu finden . Bietet auch eine modernere bereichsbasierte Überlastung.Viele Vorlagen / Ideen. Meins ist nicht so generisch oder effizient, aber ich hatte einfach das gleiche Problem und wollte es als etwas Kurzes und Süßes in die Mischung werfen. Es gewinnt auf der kürzesten Anzahl von Zeilen ... :)
quelle
substr(...)
,pop_back()
entfernen Sie das letzte Zeichen, wird dann viel klarer und sauberer.Wenn Sie möchten
std::cout << join(myVector, ",") << std::endl;
, können Sie Folgendes tun:Beachten Sie, dass diese Lösung den Join direkt in den Ausgabestream ausführt, anstatt einen sekundären Puffer zu erstellen, und mit allen Typen funktioniert, die einen Operator << für einen Ostream haben.
Dies funktioniert auch dort
boost::algorithm::join()
, wo ein Fehler auftritt, wenn Sie einvector<char*>
statt eines habenvector<string>
.quelle
quelle
std::stringstream
bei großen Arrays, dastringstream
der Speicher optimistisch zugewiesen werden kann, was zu einer Leistung von O (n.log (n)) anstelle von O (n²) für ein Array mit einer Größen
für diese Antwort führt. Auchstringstream
könnte nicht nur vorübergehend Strings bauento_string(i)
.Ich mag die Antwort von 1800. Ich würde jedoch die erste Iteration aus der Schleife verschieben, da sich die if-Anweisung nach der ersten Iteration nur einmal ändert
Dies kann natürlich auf weniger Aussagen reduziert werden, wenn Sie möchten:
quelle
++i
außer wo sie es wirklich brauchten,i++
denn nur so konnten sie dies nicht vergessen, wenn es einen Unterschied machte. (Bei mir war es übrigens dasselbe.) Sie hatten zuvor Java gelernt, wo alle Arten von C-Ismen im Trend liegen, und es dauerte einige Monate (1 Vorlesung + Laborarbeit pro Woche), aber am Ende die meisten Sie lernten die Gewohnheit, Pre-Inkrement zu verwenden.Es gibt einige interessante Versuche, eine elegante Lösung für das Problem bereitzustellen. Ich hatte die Idee, Vorlagen-Streams zu verwenden, um das ursprüngliche Dilemma des OP effektiv zu beantworten. Obwohl dies ein alter Beitrag ist, hoffe ich, dass zukünftige Benutzer, die darauf stoßen, meine Lösung als vorteilhaft empfinden.
Erstens fördern einige Antworten (einschließlich der akzeptierten Antwort) nicht die Wiederverwendbarkeit. Da C ++ keine elegante Möglichkeit bietet, Zeichenfolgen in der Standardbibliothek (wie ich gesehen habe) zu verknüpfen, ist es wichtig, eine zu erstellen, die flexibel und wiederverwendbar ist. Hier ist mein Schuss darauf:
Um dies zu verwenden, können Sie einfach Folgendes tun:
Beachten Sie, wie die Verwendung von Streams diese Lösung unglaublich flexibel macht, da wir unser Ergebnis in einem Stringstream speichern können, um es später zurückzugewinnen, oder direkt in den Standardausgang, eine Datei oder sogar in eine als Stream implementierte Netzwerkverbindung schreiben können. Der zu druckende Typ muss einfach iterierbar und mit dem Quelldatenstrom kompatibel sein. STL bietet verschiedene Streams, die mit einer Vielzahl von Typen kompatibel sind. Damit könnte man wirklich in die Stadt gehen. Auf der Oberseite meines Kopfes kann Ihr Vektor aus int, float, double, string, unsigned int, SomeObject * und mehr bestehen.
quelle
Ich habe eine Hilfskopfdatei erstellt, um eine erweiterte Join-Unterstützung hinzuzufügen.
Fügen Sie einfach den folgenden Code zu Ihrer allgemeinen Header-Datei hinzu und fügen Sie ihn bei Bedarf hinzu.
Anwendungsbeispiele:
Der Code hinter den Kulissen:
quelle
Hier ist eine generische C ++ 11-Lösung, mit der Sie dies tun können
Der Code lautet:
quelle
Das Folgende ist eine einfache und praktische Möglichkeit, Elemente in a
vector
in a umzuwandelnstring
:Sie müssen
#include <sstream>
fürostringstream
.quelle
Erweiterung des Versuchs von @sbi auf eine generische Lösung , die nicht auf
std::vector<int>
einen bestimmten Rückgabezeichenfolgentyp beschränkt ist. Der unten dargestellte Code kann folgendermaßen verwendet werden:Im ursprünglichen Code funktioniert die Ableitung von Vorlagenargumenten nicht, um den richtigen Rückgabezeichenfolgentyp zu erzeugen, wenn das Trennzeichen ein Zeichenfolgenliteral ist (wie in den obigen Beispielen). In diesem Fall sind die typedefs wie
Str::value_type
im Funktionskörper falsch. Der Code geht davon aus, dassStr
es sich immer um einen Typ handeltstd::basic_string
, sodass er für Zeichenfolgenliterale offensichtlich fehlschlägt.Um dies zu beheben, versucht der folgende Code, nur den Zeichentyp aus dem Trennzeichenargument abzuleiten, und verwendet diesen, um einen Standardrückgabezeichenfolgentyp zu erstellen. Dies wird erreicht, indem
boost::range_value
der Elementtyp aus dem angegebenen Bereichstyp extrahiert wird .Jetzt können wir problemlos eine bereichsbasierte Überladung bereitstellen, die einfach an die iteratorbasierte Überladung weitergeleitet wird:
Live-Demo bei Coliru
quelle
wie @capone tat,
Dann können wir wie folgt anrufen:
genau wie Python:
quelle
Ich benutze so etwas
quelle
Ich begann mit der Antwort von @ sbi, aber die meiste Zeit leitete ich die resultierende Zeichenfolge an einen Stream weiter, sodass die folgende Lösung erstellt wurde, die an einen Stream weitergeleitet werden kann, ohne dass der Aufwand für die Erstellung der vollständigen Zeichenfolge im Speicher anfällt.
Es wird wie folgt verwendet:
Wo string_join.h ist:
quelle
Ich habe den folgenden Code geschrieben. Es basiert auf C # string.join. Es funktioniert mit std :: string und std :: wstring und vielen Arten von Vektoren. (Beispiele in Kommentaren)
Nennen Sie es so:
Code:
quelle
Hier ist eine einfache Möglichkeit, einen Vektor von Ganzzahlen in Zeichenfolgen umzuwandeln.
quelle
Join mit Template-Funktion
Ich habe a verwendet
template
function
, um dievector
Elemente zu verbinden, und die unnötigeif
Anweisung entfernt, indem ich nur die ersten bis vorletzten Elemente in der durchlaufenvector
und dann das letzte Element nach derfor
Schleife verbunden habe. Dadurch ist auch kein zusätzlicher Code erforderlich, um das zusätzliche Trennzeichen am Ende der verknüpften Zeichenfolge zu entfernen. Also keineif
Anweisungen, die die Iteration verlangsamen, und kein überflüssiges Trennzeichen, das aufgeräumt werden muss.Dies erzeugt einen eleganten Funktionsaufruf eines beizutreten
vector
vonstring
,integer
oderdouble
usw.Ich habe zwei Versionen geschrieben: eine gibt eine Zeichenfolge zurück; der andere schreibt direkt in einen Stream.
Ausgabe
quelle