Machen Sie zuerst eine ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
Die zwei Standardmethoden sind:
Angenommen, jede Zeile besteht aus zwei Zahlen und liest Token für Token:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Zeilenbasiertes Parsen mit String-Streams:
#include <sstream>
#include <string>
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
int a, b;
if (!(iss >> a >> b)) { break; } // error
// process pair (a,b)
}
Sie sollten (1) und (2) nicht mischen, da das tokenbasierte Parsen keine Zeilenumbrüche verschlingt, sodass Sie möglicherweise falsche Leerzeilen erhalten, wenn Sie getline()
nach der tokenbasierten Extraktion das Ende von a erreichen Linie bereits.
int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
while(getline(f, line)) { }
Konstrukts und zur Fehlerbehandlung finden Sie in diesem (meinem) Artikel: gehrcke.de/2011/06/… (Ich glaube, ich brauche kein schlechtes Gewissen, um dies hier zu posten. datiert diese Antwort).Verwenden Sie
ifstream
diese Option , um Daten aus einer Datei zu lesen:Wenn Sie wirklich Zeile für Zeile lesen müssen, gehen Sie folgendermaßen vor:
Aber Sie müssen wahrscheinlich nur Koordinatenpaare extrahieren:
Aktualisieren:
In Ihrem Code verwenden Sie
ofstream myfile;
jedoch dieo
inofstream
steht füroutput
. Wenn Sie aus der Datei (Eingabe) lesen möchten, verwenden Sieifstream
. Wenn Sie sowohl lesen als auch schreiben möchten, verwenden Siefstream
.quelle
getline
ist instring
sehen , also vergessen Sie nicht die#include <string>
Das zeilenweise Lesen einer Datei in C ++ kann auf verschiedene Arten erfolgen.
[Fast] Schleife mit std :: getline ()
Der einfachste Ansatz besteht darin, einen std :: ifstream und eine Schleife mit std :: getline () -Aufrufen zu öffnen. Der Code ist sauber und leicht zu verstehen.
[Schnell] Verwenden Sie die Datei file_description_source von Boost
Eine andere Möglichkeit ist die Verwendung der Boost-Bibliothek, aber der Code wird etwas ausführlicher. Die Leistung ist dem obigen Code ziemlich ähnlich (Schleife mit std :: getline ()).
[Am schnellsten] Verwenden Sie C-Code
Wenn die Leistung für Ihre Software entscheidend ist, können Sie die Sprache C verwenden. Dieser Code kann 4-5 mal schneller sein als die obigen C ++ - Versionen, siehe Benchmark unten
Benchmark - Welches ist schneller?
Ich habe einige Leistungsbenchmarks mit dem obigen Code durchgeführt und die Ergebnisse sind interessant. Ich habe den Code mit ASCII-Dateien getestet, die 100.000 Zeilen, 1.000.000 Zeilen und 10.000.000 Textzeilen enthalten. Jede Textzeile enthält durchschnittlich 10 Wörter. Das Programm wird mit
-O3
Optimierung kompiliert und seine Ausgabe an weitergeleitet/dev/null
, um die Protokollierungszeitvariable aus der Messung zu entfernen. Zu guter Letzt protokolliert jeder Code jede Zeile mit derprintf()
Funktion für Konsistenz.Die Ergebnisse zeigen die Zeit (in ms), die jeder Code zum Lesen der Dateien benötigt hat.
Der Leistungsunterschied zwischen den beiden C ++ - Ansätzen ist minimal und sollte in der Praxis keinen Unterschied machen. Die Leistung des C-Codes macht den Benchmark beeindruckend und kann die Geschwindigkeit verändern.
quelle
std::cout
vsprintf
.printf()
Funktion in allen Fällen aus Gründen der Konsistenz verwendet wird. Ich habe auch versucht,std::cout
in allen Fällen zu verwenden, und dies machte absolut keinen Unterschied. Wie ich gerade im Text beschrieben habe, geht die Ausgabe des Programms an,/dev/null
so dass die Zeit zum Drucken der Zeilen nicht gemessen wird.cstdio
. Sie sollten es mit der Einstellung versucht habenstd::ios_base::sync_with_stdio(false)
. Ich denke, Sie hätten viel bessere Leistungen erzielt (dies ist jedoch nicht garantiert, da es implementierungsdefiniert ist, wenn die Synchronisation ausgeschaltet ist).Da Ihre Koordinaten paarweise zusammengehören, schreiben Sie doch eine Struktur für sie.
Dann können Sie einen überladenen Extraktionsoperator für istreams schreiben:
Und dann können Sie eine Koordinatendatei direkt in einen Vektor wie diesen lesen:
quelle
int
Token aus dem Stream einzulesenoperator>>
? Wie kann man es mit einem Backtracking-Parser zum Laufen bringen (dh wenn diesoperator>>
fehlschlägt, den Stream auf die vorherige Position zurücksetzen und false oder ähnliches zurückgeben)?int
Token zu lesen , wird deris
Stream ausgewertetfalse
und die Leseschleife wird an diesem Punkt beendet. Sie können dies innerhalb erkennen,operator>>
indem Sie den Rückgabewert der einzelnen Lesevorgänge überprüfen. Wenn Sie den Stream zurücksetzen möchten, würden Sie anrufenis.clear()
.operator>>
ist es korrekter zu sagen,is >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
da Sie sonst davon ausgehen, dass sich Ihr Eingabestream im Whitespace-Skipping-Modus befindet.Erweitern der akzeptierten Antwort, wenn die Eingabe lautet:
Sie können weiterhin dieselbe Logik wie folgt anwenden:
quelle
Es ist zwar nicht erforderlich, die Datei manuell zu schließen, aber es ist eine gute Idee, dies zu tun, wenn der Bereich der Dateivariablen größer ist:
quelle
Diese Antwort gilt für Visual Studio 2017 und wenn Sie aus einer Textdatei lesen möchten, welcher Speicherort relativ zu Ihrer kompilierten Konsolenanwendung ist.
Legen Sie zuerst Ihre Textdatei (in diesem Fall test.txt) in Ihrem Lösungsordner ab. Bewahren Sie die Textdatei nach dem Kompilieren mit applicationName.exe im selben Ordner auf
C: \ Benutzer \ "Benutzername" \ Quelle \ Repos \ "Lösungsname" \ "Lösungsname"
quelle
Dies ist eine allgemeine Lösung zum Laden von Daten in ein C ++ - Programm und verwendet die Readline-Funktion. Dies könnte für CSV-Dateien geändert werden, aber das Trennzeichen ist hier ein Leerzeichen.
quelle