Wie drucke ich den Inhalt eines Vektors aus?

281

Ich möchte den Inhalt eines Vektors in C ++ ausdrucken. Folgendes habe ich:

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;

int main()
{
    ifstream file("maze.txt");
    if (file) {
        vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>()));
        vector<char> path;
        int x = 17;
        char entrance = vec.at(16);
        char firstsquare = vec.at(x);
        if (entrance == 'S') { 
            path.push_back(entrance); 
        }
        for (x = 17; isalpha(firstsquare); x++) {
            path.push_back(firstsquare);
        }
        for (int i = 0; i < path.size(); i++) {
            cout << path[i] << " ";
        }
        cout << endl;
        return 0;
    }
}

Wie drucke ich den Inhalt des Vektors auf den Bildschirm?

Forthewinwin
quelle
1
Warum funktioniert es nicht?
Standard

Antworten:

392

Um Ihre Frage zu beantworten, können Sie einen Iterator verwenden:

std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

Wenn Sie den Inhalt des Vektors in der for-Schleife ändern möchten, verwenden Sie iteratorstatt const_iterator.

Aber dazu kann noch viel mehr gesagt werden. Wenn Sie nur eine Antwort wünschen, die Sie verwenden können, können Sie hier aufhören. Ansonsten lesen Sie weiter.

auto (C ++ 11) / typedef

Dies ist keine andere Lösung, sondern eine Ergänzung zu der obigen iteratorLösung. Wenn Sie den C ++ 11-Standard (oder höher) verwenden, können Sie das autoSchlüsselwort verwenden, um die Lesbarkeit zu verbessern:

for (auto i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

Der Typ von iwird jedoch nicht konstant sein (dh der Compiler wird std::vector<char>::iteratorals Typ von verwenden i).

In diesem Fall können Sie auch einfach a verwenden typedef(nicht auf C ++ 11 beschränkt und trotzdem sehr nützlich):

typedef std::vector<char> Path;
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';

Zähler

Sie können natürlich einen ganzzahligen Typ verwenden, um Ihre Position in der forSchleife aufzuzeichnen :

for(int i=0; i<path.size(); ++i)
  std::cout << path[i] << ' ';

Wenn Sie dies tun, ist es besser, die Elementtypen des Containers zu verwenden, sofern diese verfügbar und angemessen sind. Für diesen Job std::vectorwird ein Elementtyp aufgerufen: size_typeDies ist der von der sizeMethode zurückgegebene Typ .

// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
  std::cout << path[i] << ' ';

Warum nicht einfach über die iteratorLösung verwenden? In einfachen Fällen können Sie iteratordies auch tun , aber der Punkt ist, dass die Klasse ein Objekt ist, das für diese Aufgabe für kompliziertere Objekte entwickelt wurde, bei denen diese Lösung nicht ideal ist.

bereichsbasierte for-Schleife (C ++ 11)

Siehe Jefffreys Lösung . In C ++ 11 (und höher) können Sie die neue bereichsbasierte forSchleife verwenden, die folgendermaßen aussieht:

for (auto i: path)
  std::cout << i << ' ';

Da pathes sich (explizit std::vector<char>) um einen Vektor von Elementen handelt , ist das Objekt ivom Typ des Elements des Vektors (dh explizit vom Typ char). Das Objekt ihat einen Wert, der eine Kopie des tatsächlichen Elements im pathObjekt ist. Somit ibleiben nicht alle Änderungen in der Schleife an sich erhalten path. Wenn Sie darüber hinaus die Tatsache erzwingen möchten , dass Sie nicht in der Lage sein wollen , den kopierten Wert zu ändern , iin der Schleife, können Sie die Art der Gewalt izu sein const charwie folgt aus :

for (const auto i: path)
  std::cout << i << ' ';

Wenn Sie die Elemente in ändern möchten path, können Sie eine Referenz verwenden:

for (auto& i: path)
  std::cout << i << ' ';

und selbst wenn Sie nicht ändern möchten, sollten Sie path, wenn das Kopieren von Objekten teuer ist, eine const-Referenz verwenden, anstatt nach Wert zu kopieren:

for (const auto& i: path)
  std::cout << i << ' ';

std :: copy

Siehe Joshuas Antwort . Sie können den STL-Algorithmus verwenden, std::copyum den Vektorinhalt in den Ausgabestream zu kopieren. Dies ist eine elegante Lösung, wenn Sie damit vertraut sind (und außerdem ist sie sehr nützlich, nicht nur in diesem Fall, wenn Sie den Inhalt eines Vektors drucken).

std :: for_each

Siehe Max 'Lösung . Die Verwendung std::for_eachist für dieses einfache Szenario übertrieben, aber eine sehr nützliche Lösung, wenn Sie mehr als nur auf dem Bildschirm drucken möchten: Mit der Option std::for_eachkönnen Sie jede (sinnvolle) Operation am Vektorinhalt ausführen.

Überladung ostream :: operator <<

Siehe Chris 'Antwort , dies ist eher eine Ergänzung zu den anderen Antworten, da Sie bei der Überladung noch eine der oben genannten Lösungen implementieren müssen. In seinem Beispiel verwendete er einen Zähler in einer forSchleife. So können Sie beispielsweise schnell Joshuas Lösung verwenden :

template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
  if ( !v.empty() ) {
    out << '[';
    std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
    out << "\b\b]";
  }
  return out;
}

Die Verwendung einer der anderen Lösungen sollte unkompliziert sein.

Fazit

Jede der hier vorgestellten Lösungen funktioniert. Es liegt an Ihnen und dem Code, auf dem man der "Beste" ist. Alles, was detaillierter ist, bleibt wahrscheinlich am besten für eine andere Frage übrig, bei der die Vor- und Nachteile richtig bewertet werden können. Aber wie immer wird die Benutzerpräferenz immer eine Rolle spielen: Keine der vorgestellten Lösungen ist falsch, aber einige sehen für jeden einzelnen Codierer besser aus.

Nachtrag

Dies ist eine erweiterte Lösung einer früheren, die ich veröffentlicht habe. Da dieser Beitrag immer mehr Beachtung fand, habe ich mich entschlossen, ihn zu erweitern und auf die anderen hervorragenden Lösungen zu verweisen, die hier veröffentlicht wurden. Mein ursprünglicher Post hatte eine Bemerkung, dass erwähnt , wenn Sie wurden auf Modifizieren Ihr Vektor in einer Absicht , forSchleife , dann gibt es zwei , bereitgestellt durch Methoden std::vectorzum Zugriffselement: std::vector::operator[]die Grenzen nicht tun prüfen, und std::vector::atdie tun ausführen Überprüfung Grenzen. Mit anderen Worten, atwird geworfen, wenn Sie versuchen, auf ein Element außerhalb des Vektors zuzugreifen, und operator[]dies nicht tun würden. Ich habe diesen Kommentar ursprünglich nur hinzugefügt, um etwas zu erwähnen, von dem es nützlich sein könnte, zu wissen, ob dies bereits jemand getan hat. Und ich sehe jetzt keinen Unterschied. Daher dieser Nachtrag.

Zorawar
quelle
Wenn Sie eine Schleife von 0durch durchlaufen vector::size()und der Vektor innerhalb der Schleife nicht geändert wird, müssen Sie keinen at()zusätzlichen Aufwand für die Überprüfung der Grenzen verwenden. Das heißt, ich würde mit einem Iterator gehen, wie Sie vorschlagen.
Ed S.
1
@Ed: ja, es hat keinen Sinn, sich mit der, atwenn nichts in der Schleife ändert der Vektor, aber ich dachte , dass ich es nur für den Fall erwähnen würde der Vektor wird in der Schleife modifiziert (unrecommended wie das auch sein mag) , und weil es nie ein bekommt erwähnen und es könnte nützlich sein, zumindest davon zu wissen.
Zorawar
Die bereichsbasierte for-Schleife könnte wie folgt umgeschrieben werden, um Referenzen zu verwenden, die bei großen Unterobjekten wichtig sein können:for (auto const &i: path) std::cout << i << ' ';
underscore_d
@underscore_d: danke. Ich habe diesen Abschnitt aufgeräumt und hoffe, dass er jetzt vollständiger und etwas klarer ist.
Zorawar
"Überlastoperator <<" ist keine gute Lösung; Mindestens ein Operand eines überladenen Operators sollte eine von Ihrem Programm definierte Klasse sein, da eine argumentabhängige Suche erforderlich ist
MM
218

Ein viel einfacherer Weg, dies zu tun, ist mit dem Standard- Kopieralgorithmus :

#include <iostream>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator
#include <vector>

int main() {
    /* Set up vector to hold chars a-z */
    std::vector<char> path;
    for (int ch = 'a'; ch <= 'z'; ++ch)
        path.push_back(ch);

    /* Print path vector to console */
    std::copy(path.begin(), path.end(), std::ostream_iterator<char>(std::cout, " "));

    return 0;
}

Der ostream_iterator ist ein sogenannter Iteratoradapter . Es wird über dem Typ angezeigt, der im Stream ausgedruckt werden soll (in diesem Fall char). cout(auch bekannt als Konsolenausgabe) ist der Stream, in den wir schreiben möchten, und das Leerzeichen ( " ") ist das, was zwischen jedem im Vektor gespeicherten Element gedruckt werden soll.

Dieser Standardalgorithmus ist leistungsstark und viele andere auch. Die Leistung und Flexibilität, die Ihnen die Standardbibliothek bietet, machen sie so großartig. Stellen Sie sich vor: Sie können mit nur einer Codezeile einen Vektor auf die Konsole drucken . Sie müssen sich nicht mit Sonderfällen mit dem Trennzeichen befassen. Sie müssen sich keine Sorgen um For-Loops machen. Die Standardbibliothek erledigt alles für Sie.

Joshua Kravitz
quelle
3
Was passiert , wenn mein Vektor vom Typ war vector<pair<int, struct node>>. Wie verwende ich die obige Methode, um diesen Vektor zu drucken?
mtk
6
Die Trennzeichenfolge wird nach jedem Element geschrieben, nicht zwischen, dh auch nach dem letzten. Dies kann die Behandlung von Sonderfällen erfordern, wenn Sie dies nur als Trennzeichen wünschen.
Quigi
2
@mtk Sie können eine operator<<Funktion für Ihr bestimmtes Paar deklarieren <>.
ShoeLace
Es wurde eine Antwort hinzugefügt , die einen ähnlichen Ansatz zeigt, aber den obigen Kommentar von accout @Quigi: bezüglich des zusätzlichen nachgestellten Trennzeichens berücksichtigt.
dfri
@ShoeLace Gibt es keinen anderen Weg?
Thegreatcoder
69

In C ++ 11 können Sie jetzt eine bereichsbasierte for-Schleife verwenden :

for (auto const& c : path)
    std::cout << c << ' ';
Schuh
quelle
Dies funktioniert nur dann hervorragend, wenn die Größe des Vektors im Hauptteil des Bereichs für die Schleife nicht geändert wird.
Brian
8
@BrianP. Jep. Durch das Drucken der Elemente eines Containers wird der Bereich des Containers nicht geändert.
Schuh
Was ist hier vorzuziehen - c als Wertekopie oder als konstante Referenz, um das Kopieren des Elements zu vermeiden?
Kleinfreund
@kleinfreund Es kommt auf den Inhalt des Vektors an. Zum Beispiel besteht für einen Vektor von chars die Wahrscheinlichkeit, dass das Übergeben einer konstanten Referenz tatsächlich teurer ist als ein Wert. Aber hier sprechen wir von Super-Mikro-Optimierungen.
Schuh
43

Ich denke, der beste Weg, dies zu tun, besteht darin, einfach zu überladen, operator<<indem Sie diese Funktion zu Ihrem Programm hinzufügen:

#include <vector>
using std::vector;
#include <iostream>
using std::ostream;

template<typename T>
ostream& operator<< (ostream& out, const vector<T>& v) {
    out << "{";
    size_t last = v.size() - 1;
    for(size_t i = 0; i < v.size(); ++i) {
        out << v[i];
        if (i != last) 
            out << ", ";
    }
    out << "}";
    return out;
}

Dann können Sie den <<Operator für jeden möglichen Vektor verwenden, vorausgesetzt, seine Elemente haben auch Folgendes ostream& operator<<definiert:

vector<string>  s = {"first", "second", "third"};
vector<bool>    b = {true, false, true, false, false};
vector<int>     i = {1, 2, 3, 4};
cout << s << endl;
cout << b << endl;
cout << i << endl;

Ausgänge:

{first, second, third}
{1, 0, 1, 0, 0}
{1, 2, 3, 4}
Chris Redford
quelle
3
Das Speichern von v.size () - 1 als int ist ein möglicher Genauigkeitsverlust. Ich habe dies in einer akzeptierten Peer-Review-Bearbeitung ( stackoverflow.com/revisions/23397700/5 ) behoben , aber danach wurde es erneut bearbeitet, um den möglichen Genauigkeitsverlust wiederherzustellen. Ich denke, dass es in der Praxis nicht allzu wichtig ist, da Vektoren normalerweise nicht so groß sind.
JDiMatteo
Wenn Sie es nicht als Variable speichern, wird die Lesbarkeit des Codes verringert. Dies ist ein Teil Ihrer Bearbeitung, mit der ich nicht einverstanden bin. Ich habe die Art von geändert lastzu size_t.
Chris Redford
size_t last = v.size() - 1;sieht überflüssig aus, können Sie if (i) out << ", ";Bedingung vor dem out << v[i]; Link verwenden
Vladimir Gamalyan
3
Dieser Operator wird von ADL nicht gefunden, da er sich nicht im Namespace eines seiner Argumente befindet. Es wird also von allen anderen Namespaces ausgeblendet operator<<. Beispiel
MM
Wenn Sie dies tun, warum sollten Sie if (i != last) jedes Mal in der Schleife testen ? Stattdessen, wenn der Behälter nicht leer ist, dann (a) , um das erste Element zu senden, und dann (b) schlaufen senden und die restlichen Elemente den Separators Druck ersten (als Präfix). Es ist kein innerer Schleifentest (abgesehen von der Schleifenbedingung selbst) erforderlich. Es ist nur ein Out-of-Loop-Test erforderlich.
WhozCraig
22

Wie wäre es mit for_each+ Lambda-Ausdruck :

#include <vector>
#include <algorithm>
...
std::vector<char> vec;
...
std::for_each(
              vec.cbegin(),
              vec.cend(),
              [] (const char c) {std::cout << c << " ";} 
              );
...

Natürlich ein Range-basiertes für die konkreteste Lösung für diese konkrete Aufgabe, aber diese bietet auch viele andere Möglichkeiten.

Erläuterung

Der for_eachAlgorithmus verwendet einen Eingabebereich und ein aufrufbares Objekt und ruft dieses Objekt für jedes Element des Bereichs auf. Ein Eingabebereich wird durch zwei Iteratoren definiert . Ein aufrufbares Objekt kann eine Funktion, ein Zeiger auf eine Funktion, ein Objekt einer Klasse sein, die überladen ist, () operatoroder wie in diesem Fall ein Lambda-Ausdruck . Der Parameter für diesen Ausdruck entspricht dem Typ der Elemente aus dem Vektor.

Das Schöne an dieser Implementierung ist die Leistung, die Sie durch Lambda-Ausdrücke erhalten. Sie können diesen Ansatz für viel mehr Dinge verwenden, als nur den Vektor zu drucken.

Maxim Chetrusca
quelle
10

Kopieren Sie einfach den Container auf die Konsole.

std::vector<int> v{1,2,3,4};
std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout, " " ));

Sollte ausgeben:

1 2 3 4
g24l
quelle
8

Das Problem liegt wahrscheinlich in der vorherigen Schleife : (x = 17; isalpha(firstsquare); x++). Diese Schleife wird überhaupt nicht ausgeführt (wenn firstsquarees sich nicht um Alpha handelt) oder für immer ausgeführt (wenn es sich um Alpha handelt). Der Grund ist, dass sich firstsquaredas nicht ändert, wenn xes erhöht wird.

MSalters
quelle
7

In C ++ 11 ist eine bereichsbasierte for-Schleife möglicherweise eine gute Lösung:

vector<char> items = {'a','b','c'};
for (char n : items)
    cout << n << ' ';

Ausgabe:

a b c 
dummgottdamnjerk
quelle
6

Verwenden Sie std::copyjedoch ohne zusätzliches nachlaufendes Trennzeichen

Ein alternativer / modifizierter Ansatz mit std::copy(wie ursprünglich in der Antwort von @JoshuaKravtiz verwendet ), jedoch ohne ein zusätzliches nachfolgendes Trennzeichen nach dem letzten Element:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template <typename T>
void print_contents(const std::vector<T>& v, const char * const separator = " ")
{
    if(!v.empty())
    {
        std::copy(v.begin(),
                  --v.end(),
                  std::ostream_iterator<T>(std::cout, separator));
        std::cout << v.back() << "\n";
    }
}

// example usage
int main() {
    std::vector<int> v{1, 2, 3, 4};
    print_contents(v);      // '1 2 3 4'
    print_contents(v, ":"); // '1:2:3:4'
    v = {};
    print_contents(v);      // ... no std::cout
    v = {1};
    print_contents(v);      // '1'
    return 0;
}

Beispiel für die Verwendung eines Containers eines benutzerdefinierten POD-Typs:

// includes and 'print_contents(...)' as above ...

class Foo
{
    int i;
    friend std::ostream& operator<<(std::ostream& out, const Foo& obj);
public:
    Foo(const int i) : i(i) {}
};

std::ostream& operator<<(std::ostream& out, const Foo& obj)
{
    return out << "foo_" << obj.i; 
}

int main() {
    std::vector<Foo> v{1, 2, 3, 4};
    print_contents(v);      // 'foo_1 foo_2 foo_3 foo_4'
    print_contents(v, ":"); // 'foo_1:foo_2:foo_3:foo_4'
    v = {};
    print_contents(v);      // ... no std::cout
    v = {1};
    print_contents(v);      // 'foo_1'
    return 0;
}
dfri
quelle
3

Ich sehe zwei Probleme. Wie bereits erwähnt, for (x = 17; isalpha(firstsquare); x++)gibt es entweder eine Endlosschleife oder sie wird überhaupt nicht ausgeführt. if (entrance == 'S')Wenn sich das Eingangszeichen von 'S' unterscheidet, wird nichts in den Pfadvektor verschoben, wodurch dieser leer wird und somit nichts auf dem Bildschirm gedruckt wird. Sie können letzteres testen, um zu prüfen path.empty()oder zu druckenpath.size() .

Wäre es nicht besser, einen String anstelle eines Vektors zu verwenden? Sie können wie ein Array auch auf den Inhalt der Zeichenfolge zugreifen, nach Zeichen suchen, Teilzeichenfolgen extrahieren und die Zeichenfolge einfach (ohne Schleife) drucken.

Wenn Sie alles mit Strings machen, können Sie es möglicherweise weniger kompliziert schreiben und das Problem leichter erkennen.

Miguelbernadi
quelle
3

Überlastungsoperator <<:

template<typename OutStream, typename T>
OutStream& operator<< (OutStream& out, const vector<T>& v)
{
    for (auto const& tmp : v)
        out << tmp << " ";
    out << endl;
    return out;
}

Verwendungszweck:

vector <int> test {1,2,3};
wcout << test; // or any output stream
ivanmara
quelle
3

Diese Antwort basiert auf der Antwort von Zorawar, aber ich konnte dort keinen Kommentar hinterlassen.

Sie können die automatische (C ++ 11) / typedef-Version const erstellen, indem Sie stattdessen cbegin und cend verwenden

for (auto i = path.cbegin(); i != path.cend(); ++i)
    std::cout << *i << ' ';
SketchyManDan
quelle
1

In C ++ 11``

for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';

for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Akash Kandpal
quelle
Diese Antwort enthält keine zusätzlichen Informationen im Vergleich zu den bereits vorhandenen Antworten.
Yashas
0
#include<bits/stdc++.h>
using namespace std;

int main()
{
    vector <pair<string,int> > v;
    int n;
    cin>>n;
int i;
    for( i=0;i<n;i++)
    {
        int  end;
        string str;
        cin>>str;
        cin>>end;
        v.push_back(make_pair(str,end));
    }



for (int j=0;j<n;j++)
{
    cout<<v[j].first<< " "<<v[j].second<<endl;
}``
}
Bishal B Sonar
quelle
2
Hallo! Willkommen bei stackoverflow. Es wäre großartig, wenn Sie dem Code-Snippet eine Erklärung hinzufügen könnten, was Sie tun und wie es die Frage beantwortet.
Slabgorb
2
Vielleicht möchten Sie lesen: Warum sollte ich <bits / stdc ++. H> nicht # einschließen?
Blastfurnace
0

Das hat bei mir funktioniert:

    for (auto& i : name)
    {
    int r = 0;
    for (int j = 0; j < name[r].size();j++) 
    {
    std::cout << i[j];
    }
    r++;
    std::cout << std::endl;
    }
Tempi Skat
quelle
0

Für diejenigen, die interessiert sind: Ich habe eine verallgemeinerte Lösung geschrieben, die das Beste aus beiden Welten nutzt, auf jeden Bereichstyp verallgemeinert ist und nicht arithmetische Typen in Anführungszeichen setzt (erwünscht für stringähnliche Typen). Darüber hinaus sollte dieser Ansatz keine ADL-Probleme aufweisen und auch „Überraschungen“ vermeiden (da er von Fall zu Fall explizit hinzugefügt wird):

template <typename T>
inline constexpr bool is_string_type_v = std::is_convertible_v<const T&, std::string_view>;

template<class T>
struct range_out {
  range_out(T& range) : r_(range) {
  }
  T& r_;
  static_assert(!::is_string_type_v<T>, "strings and string-like types should use operator << directly");
};

template <typename T>
std::ostream& operator<< (std::ostream& out, range_out<T>& range) {
  constexpr bool is_string_like = is_string_type_v<T::value_type>;
  constexpr std::string_view sep{ is_string_like ? "', '" : ", " };

  if (!range.r_.empty()) {
    out << (is_string_like ? "['" : "[");
    out << *range.r_.begin();
    for (auto it = range.r_.begin() + 1; it != range.r_.end(); ++it) {
      out << sep << *it;
    }
    out << (is_string_like ? "']" : "]");
  }
  else {
    out << "[]";
  }

  return out;
}

Jetzt ist es ziemlich einfach in jedem Bereich zu verwenden:

std::cout << range_out{ my_vector };

Der stringartige Check lässt Raum für Verbesserungen. Ich habe auch static_assertmeine Lösung eingecheckt std::basic_string<>, um dies zu vermeiden , aber ich habe sie hier der Einfachheit halber weggelassen.

Darune
quelle
-1

Sie können Ihre eigene Funktion schreiben:

void printVec(vector<char> vec){
    for(int i = 0; i < vec.size(); i++){
        cout << vec[i] << " ";
    }
    cout << endl;
}
Dolev Ben
quelle
-1

Für Leute, die Einzeiler ohne Schleifen wollen:

Ich kann nicht glauben, dass niemand daran gedacht hat, aber vielleicht liegt es an dem eher C-ähnlichen Ansatz. Wie auch immer, es ist absolut sicher, dies ohne eine Schleife in einem Einzeiler zu tun, vorausgesetzt , die std::vector<char>ist nullterminiert:

std::vector<char> test { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' };
std::cout << test.data() << std::endl;

Aber ich würde das in die einwickeln ostream Operator einwickeln, wie @Zorawar vorgeschlagen hat, nur um sicher zu gehen:

template <typename T>std::ostream& operator<< (std::ostream& out, std::vector<T>& v)
{
    v.push_back('\0'); // safety-check!
    out << v.data();
    return out;
}

std::cout << test << std::endl; // will print 'Hello, world!'

Wir können ein ähnliches Verhalten erreichen, indem wir verwenden printf stattdessen verwenden:

fprintf(stdout, "%s\n", &test[0]); // will also print 'Hello, world!'

HINWEIS:

Der überladene ostreamOperator muss den Vektor als nicht konstant akzeptieren. Dies kann das Programm unsicher machen oder missbräuchlichen Code einführen. Da ein Nullzeichen angehängt wird, kann es auch zu einer Neuzuweisung des Zeichens std::vectorkommen. Die Verwendung von for-Schleifen mit Iteratoren wird daher wahrscheinlich schneller sein.

ワ イ き ん ぐ
quelle
1
1. unterscheidet fprintf(stdout, "%s\n", &test[0]);sich nicht von std::cout << test.data(), beide erfordern einen nullterminierten Vektor. 2. Der Operator "Aber ich würde dies in den Ostream-Operator einschließen" << , der den richtigen Operanden ändert, ist eine sehr schlechte Idee.
HolyBlackCat
Ich habe fprintf(stdout, "%s\n", &test[0]);lange Zeit Code verwendet, ohne dass es mir jemals Probleme bereitete. Interessant! Und ich stimme zu, dass es nicht so schön ist, den Vektor im ostreamOperator zu ändern , aber ich mag es nicht, sowohl manuell zu schleifen als auch Iteratoren zu verwenden. Irgendwie habe ich das Gefühl, dass bei einfachen Vorgängen wie dem Drucken eine std::vector<char>Standardbibliothek diese Dinge verstecken sollte. Aber C ++ entwickelt sich ständig weiter, es könnte bald kommen.
ぐ イ き ん