
Zwickmühle
Ich weiß, wie man das in anderen Sprachen macht, aber nicht in C++, das ich hier verwenden muss.
Ich habe einen Satz Saiten (keywords
), auf die ich drucke out
als Liste, und die Zeichenfolgen benötigen ein Komma zwischen ihnen, aber kein nachgestelltes Komma. In Java würde ich zum Beispiel a verwenden StringBuilder
und lösche einfach das Komma am Ende, nachdem ich meine Zeichenfolge erstellt habe. Wie kann ich das in C++ machen?
auto iter = keywords.begin();
for (iter; iter != keywords.end( ); iter++ )
{
out << *iter << ", ";
}
out << endl;
Ich habe zunächst versucht, den folgenden Block einzufügen, um dies zu tun (Verschieben des Kommadrucks hier):
if (iter++ != keywords.end())
out << ", ";
iter--;
In einem experimentellen C++17-fähigen Compiler, der Ihnen bald zur Verfügung steht, können Sie verwenden std::experimental::ostream_joiner
:
#include <algorithm>
#include <experimental/iterator>
#include <iostream>
#include <iterator>
int main()
{
int i[] = {1, 2, 3, 4, 5};
std::copy(std::begin(i),
std::end(i),
std::experimental::make_ostream_joiner(std::cout, ", "));
}
Live-Beispiele mit GCC 6.0 SVN und Klingeln 3.9 SVN
Unter der Annahme eines vage normalen Ausgabestroms, sodass das Schreiben einer leeren Zeichenfolge tatsächlich nichts bewirkt:
const char *padding = "";
for (auto iter = keywords.begin(); iter != keywords.end(); ++iter) {
out << padding << *iter;
padding = ", "
}
Ein üblicher Ansatz besteht darin, das erste Element vor der Schleife zu drucken und nur die verbleibenden Elemente zu durchlaufen, wobei vor jedem verbleibenden Element ein Komma vorgedruckt wird.
Alternativ sollten Sie in der Lage sein, Ihren eigenen Stream zu erstellen, der einen aktuellen Status der Zeile (vor endl) beibehält und Kommas an die entsprechende Stelle setzt.
BEARBEITEN: Sie können auch eine in der Mitte getestete Schleife verwenden, wie von TED vorgeschlagen. Es wäre so etwas wie:
if(!keywords.empty())
{
auto iter = keywords.begin();
while(true)
{
out << *iter;
++iter;
if(iter == keywords.end())
{
break;
}
else
{
out << ", ";
}
}
}
Ich habe zuerst die Methode “Erstes Element vor der Schleife drucken” erwähnt, weil sie den Schleifenkörper wirklich einfach hält, aber alle Ansätze funktionieren gut.

Matthias M.
Es gibt viele clevere Lösungen und zu viele, die den Code hoffnungslos verstümmeln, ohne den Compiler seine Arbeit machen zu lassen.
Die Die offensichtliche Lösung besteht darin, die erste Iteration in einem Sonderfall auszuführen:
bool first = true;
for (auto const& e: sequence) {
if (first) { first = false; } else { out << ", "; }
out << e;
}
Es ist ein absolut einfaches Muster, das:
- Verstümmelt die Schleife nicht: Es ist immer noch auf einen Blick ersichtlich, dass jedes Element wiederholt wird.
- Ermöglicht mehr als nur das Einfügen eines Trennzeichens oder das Drucken einer Liste, da die
else
-Block und der Schleifenkörper können beliebige Anweisungen enthalten.
Es ist vielleicht nicht der absolut effizienteste Code, aber der potenzielle Leistungsverlust eines einzelnen gut vorhergesagten Zweigs wird sehr wahrscheinlich von dem gewaltigen Ungetüm überschattet, das es gibt std::ostream::operator<<
.
9960200cookie-checkWie kann ich eine Liste von Elementen drucken, die durch Kommas getrennt sind?yes
Ich weiß, dass es für eine kürzere Linie sorgt, aber Sie sollten wirklich verwenden
for (auto iter = ...;
zu bindeniter
in den Gültigkeitsbereich der Schleife, es sei denn, Sie beabsichtigen ausdrücklich, sie später zu verwenden.– mager
♦
16. August 2010 um 20:27 Uhr
@πάνταῥεῖ Obwohl es sich um Duplikate handelt, warum ist die Schließung nicht umgekehrt? Dieser Posten scheint sicherlich ein besserer Kandidat als betrügerisches Ziel zu sein.
– Passant
3. Oktober 2020 um 16:32 Uhr