Um einen ifstream
(oder wirklich jeden beliebigen Eingabestream) in einem Formular zu tarnen, das wie ein Iterator funktioniert, möchten Sie die Vorlagenklasse istream_iterator
oder istreambuf_iterator
verwenden. Ersteres ist nützlich für Dateien, bei denen die Formatierung von Bedeutung ist. Zum Beispiel kann eine Datei voller Leerzeichen getrennte ganze Zahlen in den Iterator Bereich Konstrukteurs-Vektor wie folgt gelesen werden:
#include <fstream>
#include <vector>
#include <iterator> // needed for istream_iterator
using namespace std;
int main(int argc, char** argv)
{
ifstream infile("my-file.txt");
// It isn't customary to declare these as standalone variables,
// but see below for why it's necessary when working with
// initializing containers.
istream_iterator<int> infile_begin(infile);
istream_iterator<int> infile_end;
vector<int> my_ints(infile_begin, infile_end);
// You can also do stuff with the istream_iterator objects directly:
// Careful! If you run this program as is, this won't work because we
// used up the input stream already with the vector.
int total = 0;
while (infile_begin != infile_end) {
total += *infile_begin;
++infile_begin;
}
return 0;
}
istreambuf_iterator
durch lesen verwendet wird, um Dateien ein einzelnes Zeichen in einer Zeit, die Formatierung der Eingabe ohne Berücksichtigung . Das bedeutet, dass Sie alle Zeichen einschließlich Leerzeichen, Zeilenumbrüche usw. zurückgeben. Abhängig von Ihrer Anwendung ist dies möglicherweise sinnvoller.
Hinweis: Scott Meyers erklärt in Wirksame STL warum die separaten Variablen Deklarationen für istream_iterator
oben benötigt werden. Normalerweise würden Sie so etwas tun:
ifstream infile("my-file.txt");
vector<int> my_ints(istream_iterator<int>(infile), istream_iterator<int>());
jedoch C++ parst tatsächlich die zweite Zeile in einer unglaublich bizarre Art und Weise. Sie sieht es als Deklaration einer Funktion namens my_ints
, die zwei Parameter akzeptiert und eine vector<int>
zurückgibt. Der erste Parameter ist vom Typ istream_iterator<int>
und heißt infile
(die Klammern werden ignoriert). Der zweite Parameter ist ein Funktionszeiger ohne Namen, der (aufgrund der Klammern) null Argumente annimmt und ein Objekt vom Typ istream_iterator<int>
zurückgibt.
Ziemlich cool, aber auch ziemlich ärgerlich, wenn Sie nicht darauf achten.
EDIT
Hier ist ein Beispiel für die istreambuf_iterator
Verwendung in einer Datei von 64-Bit-Zahlen gelegt lesen End-to-end:
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char** argv)
{
ifstream input("my-file.txt");
istreambuf_iterator<char> input_begin(input);
istreambuf_iterator<char> input_end;
// Fill a char vector with input file's contents:
vector<char> char_input(input_begin, input_end);
input.close();
// Convert it to an array of unsigned long with a cast:
unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]);
size_t num_long_elements = char_input.size() * sizeof(char)/sizeof(unsigned long);
// Put that information into a vector:
vector<unsigned long> long_input(converted, converted + num_long_elements);
return 0;
}
Nun, ich persönlich eher nicht mögen diese Lösung (mit reinterpret_cast
, ausgesetzt char_input
's-Array), aber ich bin nicht vertraut genug mit istreambuf_iterator
, um bequem eine templatized über 64-Bit-Zeichen, die th machen würde ist viel einfacher.
Sind die ganzen Zahlen in der Datei durch Zeilenumbrüche, Leerzeichen usw. getrennt? Wenn ja, ist der 'istream_iterator' dein Freund. – Dawson
@Toolbox Danke für die Antwort und die Lösung!Das Format der Dateien ist binäre, 64-Bit-Little-Endian-Ganzzahlen ohne Vorzeichen ohne Trennzeichen. Sieht also aus wie istreambuf_iterator ist der Weg zu gehen? Kannst du helfen, istrebbuf_iterator als Vektor zu tarnen? –
Donny
Sicher! Gib mir ein paar Momente, um etwas hochzupeitschen (und stelle sicher, dass es kompiliert wird). – Dawson