Ich codiere ein Programm, das Daten direkt von Benutzereingaben liest, und habe mich gefragt, wie ich (ohne Schleifen) alle Daten bis zur EOF von der Standardeingabe lesen kann. Ich habe überlegt, es zu verwenden, cin.get( input, '\0' )
aber es '\0'
ist nicht wirklich das EOF-Zeichen, das nur bis EOF liest oder '\0'
je nachdem, was zuerst eintritt.
Oder ist die Verwendung von Schleifen der einzige Weg, dies zu tun? Wenn ja, wie geht das am besten?
Verwenden von Schleifen:
#include <iostream> using namespace std; ... // numbers int n; while (cin >> n) { ... } // lines string line; while (getline(cin, line)) { ... } // characters char c; while (cin.get(c)) { ... }
Ressource
quelle
Sie können dies ohne explizite Schleifen tun, indem Sie Stream-Iteratoren verwenden. Ich bin sicher, dass es intern eine Art Schleife verwendet.
#include <string> #include <iostream> #include <istream> #include <ostream> #include <iterator> int main() { // don't skip the whitespace while reading std::cin >> std::noskipws; // use stream iterators to copy the stream to a string std::istream_iterator<char> it(std::cin); std::istream_iterator<char> end; std::string results(it, end); std::cout << results; }
quelle
Nachdem ich die Lösung von KeithB mit untersucht hatte
std::istream_iterator
, entdeckte ich diestd:istreambuf_iterator
.Testen Sie das Programm, um alle eingespeisten Eingaben in eine Zeichenfolge zu lesen, und schreiben Sie sie dann erneut aus:
#include <iostream> #include <iterator> #include <string> int main() { std::istreambuf_iterator<char> begin(std::cin), end; std::string s(begin, end); std::cout << s; }
quelle
std::istreambuf_iterator
anstelle vonstd::istream_iterator
, aber wofür?Wahrscheinlich am einfachsten und allgemein effizient:
#include <iostream> int main() { std::cout << std::cin.rdbuf(); }
Verwenden Sie bei Bedarf Streams anderer Typen, z. B.
std::ostringstream
als Puffer, anstelle des Standardausgabestreams.quelle
std::ostringstream std_input; std_input << std::cin.rdbuf(); std::string s = std_input.str()
. Sie haben alle Eingaben ins
(seien Sie vorsichtig,std::string
wenn die Eingabe zu groß ist)Sie können die Funktion std :: istream :: getline () (oder vorzugsweise die Version, die mit std :: string funktioniert) verwenden, um eine ganze Zeile abzurufen . Beide haben Versionen, mit denen Sie das Trennzeichen (Zeilenendezeichen) angeben können. Der Standardwert für die Zeichenfolgenversion ist '\ n'.
quelle
Traurige Randnotiz: Ich habe mich für C ++ IO entschieden, um mit Boost-basiertem Code konsistent zu sein. Aus den Antworten auf diese Frage habe ich gewählt
while (std::getline(std::cin, line))
. Mit g ++ Version 4.5.3 (-O3) in Cygwin (Mintty) habe ich einen Durchsatz von 2 MB / s. Microsoft Visual C ++ 2010 (/ O2) hat es für denselben Code auf 40 MB / s gebracht.Nach dem Umschreiben des E
while (fgets(buf, 100, stdin))
/ A auf reines C stieg der Durchsatz in beiden getesteten Compilern auf 90 MB / s. Das macht einen Unterschied für jeden Eingang, der größer als 10 MB ist ...quelle
std::ios::sync_with_stdio(false);
vor Ihrer while-Schleife hinzu.cin.tie(NULL);
kann auch helfen, wenn Sie Lesen und Schreiben verschachteln.while(std::cin) { // do something }
quelle
// do something
keine zusätzlichen Überprüfungen der Rückgabewerte von E / A-Operationen enthalten sind und die darin enthaltene Überprüfung bedeutungslos ist.Warten Sie, verstehe ich Sie richtig? Sie verwenden cin für die Tastatureingabe und möchten das Lesen von Eingaben beenden, wenn der Benutzer das EOF-Zeichen eingibt? Warum sollte der Benutzer jemals das EOF-Zeichen eingeben? Oder wollten Sie nicht mehr aus einer Datei im EOF lesen?
Wenn Sie tatsächlich versuchen, ein EOF-Zeichen mit cin zu lesen, geben Sie dann einfach das EOF als Trennzeichen an.
// Needed headers: iostream char buffer[256]; cin.get( buffer, '\x1A' );
Wenn Sie das Lesen aus einer Datei in der EOF beenden möchten, verwenden Sie einfach getline und geben Sie die EOF erneut als Trennzeichen an.
// Needed headers: iostream, string, and fstream string buffer; ifstream fin; fin.open("test.txt"); if(fin.is_open()) { getline(fin,buffer,'\x1A'); fin.close(); }
quelle
Eine Möglichkeit besteht darin, einen Container zu verwenden, z
std::vector<char> data;
und leiten Sie alle Eingaben in diese Sammlung um, bis sie
EOF
empfangen werden, d. hstd::copy(std::istream_iterator<char>(std::cin), std::istream_iterator<char>(), std::back_inserter(data));
Der verwendete Container muss jedoch möglicherweise zu oft Speicher neu zuweisen, oder Sie beenden mit einer
std::bad_alloc
Ausnahme, wenn Ihr System nicht mehr über genügend Speicher verfügt. Um diese Probleme zu lösen, können Sie eine feste Anzahl von Elementen reservierenN
und diese Anzahl von Elementen isoliert verarbeiten, d. H.data.reserve(N); while (/*some condition is met*/) { std::copy_n(std::istream_iterator<char>(std::cin), N, std::back_inserter(data)); /* process data */ data.clear(); }
quelle