Najpierw wykonaj ifstream
:
#include <fstream>
std::ifstream infile("thefile.txt");
Dwie standardowe metody to:
Załóżmy, że każda linia składa się z dwóch liczb i odczytuje token po tokenie:
int a, b;
while (infile >> a >> b)
{
// process pair (a,b)
}
Analiza liniowa przy użyciu strumieni ciągów:
#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)
}
Nie powinieneś mieszać (1) i (2), ponieważ parsowanie oparte na tokenach nie pożera nowych linii, więc możesz skończyć z fałszywymi pustymi liniami, jeśli użyjesz getline()
po wyodrębnieniu opartym na tokenach doszedł do końca linia już.
int a, b; char c; while ((infile >> a >> c >> b) && (c == ','))
while(getline(f, line)) { }
konstrukcji i dotyczące obsługi błędów, zapoznaj się z tym (moim) artykułem: gehrcke.de/2011/06/… (Myślę, że nie muszę mieć złego sumienia, zamieszczając to tutaj, nawet nieco wcześniej datuje tę odpowiedź).Służy
ifstream
do odczytu danych z pliku:Jeśli naprawdę potrzebujesz czytać wiersz po wierszu, wykonaj następujące czynności:
Ale prawdopodobnie musisz po prostu wyodrębnić pary współrzędnych:
Aktualizacja:
W swoim kodzie używasz
ofstream myfile;
, jednako
inofstream
oznaczaoutput
. Jeśli chcesz czytać z pliku (wejście) użyjifstream
. Jeśli chcesz zarówno czytać, jak i pisać, użyjfstream
.źródło
getline
jeststring
widoczny , więc nie zapomnij o#include <string>
Czytanie pliku wiersz po wierszu w C ++ można wykonać na kilka różnych sposobów.
[Fast] Pętla ze std :: getline ()
Najprostszym podejściem jest otwarcie std :: ifstream i zapętlenie za pomocą wywołań std :: getline (). Kod jest czysty i łatwy do zrozumienia.
[Szybko] Użyj Boost's file_description_source
Inną możliwością jest użycie biblioteki Boost, ale kod staje się bardziej szczegółowy. Wydajność jest dość podobna do powyższego kodu (Loop with std :: getline ()).
[Najszybszy] Użyj kodu C.
Jeśli wydajność ma kluczowe znaczenie dla twojego oprogramowania, możesz rozważyć użycie języka C. Ten kod może być 4-5 razy szybszy niż wersje C ++ powyżej, patrz test porównawczy poniżej
Benchmark - Który jest szybszy?
Z powyższym kodem przeprowadziłem kilka testów wydajności, a wyniki są interesujące. Przetestowałem kod z plikami ASCII, które zawierają 100 000 wierszy, 1 000 000 wierszy i 10 000 000 wierszy tekstu. Każdy wiersz tekstu zawiera średnio 10 słów. Program jest kompilowany z
-O3
optymalizacją, a jego dane wyjściowe są przekazywane do/dev/null
w celu usunięcia zmiennej czasowej rejestrowania z pomiaru. Na koniec każdy fragment kodu rejestruje każdą linię za pomocąprintf()
funkcji zapewniającej spójność.Wyniki pokazują czas (w ms), jaki każdy fragment kodu potrzebował na odczyt plików.
Różnica w wydajności między dwoma podejściami C ++ jest minimalna i nie powinna robić żadnej różnicy w praktyce. Wydajność kodu C sprawia, że test porównawczy robi wrażenie i może być przełomem pod względem szybkości.
źródło
std::cout
vsprintf
.printf()
we wszystkich przypadkach korzystać z funkcji w celu zachowania spójności. Próbowałem też używaćstd::cout
we wszystkich przypadkach i to absolutnie nie miało znaczenia. Jak właśnie opisałem w tekście, wyjście programu idzie do,/dev/null
więc czas drukowania linii nie jest mierzony.cstdio
. Powinieneś spróbować z ustawieniemstd::ios_base::sync_with_stdio(false)
. Sądzę, że uzyskałbyś znacznie lepszą wydajność (nie jest to jednak gwarantowane, ponieważ jest zdefiniowane w implementacji, gdy synchronizacja jest wyłączona).Ponieważ twoje współrzędne należą do siebie jako pary, dlaczego nie napisać dla nich struktury?
Następnie możesz napisać przeciążony operator ekstrakcji dla istreams:
A potem możesz odczytać plik współrzędnych prosto do wektora takiego:
źródło
int
tokenów ze strumieniaoperator>>
? W jaki sposób można sprawić, by działał z analizatorem składni cofania (tj. Gdyoperator>>
zawiedzie, przywróć strumień do poprzedniej pozycji, zwróć wartość false lub coś takiego)?int
tokenów,is
strumień oceni na,false
a pętla odczytu zakończy się w tym momencie. Możesz to wykryćoperator>>
, sprawdzając wartość zwrotną poszczególnych odczytów. Jeśli chcesz wycofać strumień, zadzwońis.clear()
.operator>>
bardziej poprawne jest powiedzenie,is >> std::ws >> coordinates.x >> std::ws >> coordinates.y >> std::ws;
ponieważ w przeciwnym razie zakładasz, że twój strumień wejściowy jest w trybie pomijania białych znaków.Rozwijanie przyjętej odpowiedzi, jeśli dane wejściowe to:
nadal będziesz mógł zastosować tę samą logikę:
źródło
Chociaż nie ma potrzeby ręcznego zamykania pliku, ale warto to zrobić, jeśli zakres zmiennej pliku jest większy:
źródło
Ta odpowiedź dotyczy programu Visual Studio 2017 i jeśli chcesz czytać z pliku tekstowego, która lokalizacja jest względna w stosunku do skompilowanej aplikacji konsoli.
najpierw umieść plik tekstowy (w tym przypadku test.txt) w folderze rozwiązania. Po skompilowaniu trzymaj plik tekstowy w tym samym folderze z applicationName.exe
C: \ Users \ "nazwa użytkownika" \ source \ repos \ "nazwa rozwiązania" \ "nazwa rozwiązania"
źródło
Jest to ogólne rozwiązanie do ładowania danych do programu C ++ i wykorzystuje funkcję readline. Można to zmodyfikować dla plików CSV, ale separator jest tutaj spacją.
źródło