Wie kann ich eine Liste von Elementen drucken, die durch Kommas getrennt sind?

Lesezeit: 4 Minuten

Wie kann ich eine Liste von Elementen drucken die durch
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--;

  • Ich weiß, dass es für eine kürzere Linie sorgt, aber Sie sollten wirklich verwenden for (auto iter = ...; zu binden iter 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

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

  • Ich mag das. Das ist kurz und knapp. Gibt es eine Möglichkeit, eine Transformation anzuwenden, ohne std::transform zu verwenden, da dies die Erstellung eines Zwischenspeichers erforderte?

    – kshenoy

    30. April 2018 um 22:04 Uhr

  • hat dies den experimentellen Status bestanden? Ich konnte nicht finden std::ostream_joiner in allen späteren Versionen

    – phuklv

    9. Juni 2021 um 3:57 Uhr

  • Dies ist die kanonische Containerdruckerschleife. Wenn Sie es leid sind, es jedes Mal zu schreiben, haben wir einen magischen Helfer-Header erstellt, der genau das für alle Container tut. Der einzige Kommentar ist, dass, wenn alles ausreichend konstant ist und Sie den Iterator nach der Schleife nicht benötigen, der Schleifenkopf auf geändert wird for (auto iter = keywords.begin(), end = keywords.end(); iter != end; ++iter).

    – Kerrek SB

    7. Juni 2011 um 23:42 Uhr


  • Alternativ, wenn Sie Ja wirklich Wenn Sie den Vergleich nicht jedes Mal wiederholen möchten, können Sie dies tun auto it = keywords.begin(); if (it != keywords.end()) cout << it++; und dann Führen Sie die Schleife mit dem Körper aus cout << ", " << it;. Ich persönlich bevorzuge es jedoch, alles an einem Ort zu halten.

    – Kerrek SB

    7. Juni 2011 um 23:50 Uhr

  • @Kerrek SB – … oder Sie könnten einfach eine in der Mitte getestete Schleife verwenden. Jedes Mal, wenn Sie feststellen, dass Sie eine Schleife mit der Logik „bei der ersten (oder bei der letzten) Iteration auch tun“ schreiben, besteht eine sehr gute Chance, dass Sie eine natürliche, in der Mitte getestete Schleife an Ihren Händen haben.

    – TED

    8. Juni 2011 um 13:32 Uhr

  • @TED: Was ist eine “mittlere Testschleife”?

    – Kerrek SB

    8. Juni 2011 um 13:43 Uhr

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 = ", "
}

  • Hatte Gelegenheit, diese Frage zwei Jahre später noch einmal zu betrachten, und ich mag diesen Ansatz ziemlich. Klug.

    – TED

    29. Juni 2012 um 18:52 Uhr

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.

  • Hatte Gelegenheit, diese Frage zwei Jahre später noch einmal zu betrachten, und ich mag diesen Ansatz ziemlich. Klug.

    – TED

    29. Juni 2012 um 18:52 Uhr

Wie kann ich eine Liste von Elementen drucken die durch
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:

  1. Verstümmelt die Schleife nicht: Es ist immer noch auf einen Blick ersichtlich, dass jedes Element wiederholt wird.
  2. 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<<.

996020cookie-checkWie kann ich eine Liste von Elementen drucken, die durch Kommas getrennt sind?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy