Probleme beim Einlesen
-
Hallo

ich muss für eine Hausarbeit für die Uni aus zwei Dateien jeweils Werte aus Spalten einlesen.
# Kommentar # Kommentar # Kommentar # Kommentar 3020.81108 14.082 0.006 3021.83499 14.044 0.006 3023.69700 14.030 0.006 ...void read_data(vector<vector<double> > &dataset){ ifstream in; in.open("lmc.dat", ios::out); if(in.is_open()!=1)cout<<"Datei konnte nicht geöffnet werden!"<<endl; int i=0; double t; double X_t; double sigma; while(!in.eof()){ in>>t; in>>X_t; in>>sigma; dataset.push_back(vector<double>()); dataset[i].push_back(t);//Zeit dataset[i].push_back(X_t);//Signal dataset[i].push_back(sigma);//Signal i++; } }Diese Funktion schafft es die Werte auszulesen, wenn ich vorher die Kommentarzeilen manuell entferne. Das ist aber in der Hausarbeit nicht zulässig. Wie schaffe ich es, dass mit # beginnende Zeilen ignoriert werden?
Die andere Datei sieht folgendermaßen aus:
# Kommentar # Kommentar 1.00000000 0.822350740 -0.291915804 2.00000000 2.59992409 1.19528222 3.00000000 1.06593728 0.250372231 4.00000000 -0.361742496 -0.242994726 7.00000000 0.319537908 0.513922453 8.00000000 -0.471693277 -0.476872563 ...Im Gegensatz zur ersten Datei sind die Spalten nicht durch Tabs getrennt, sondern durch Leertasten (sogar vor der ersten Spalte). Hier versagt mein Programm auf ganzer Linie.
Ich muss eine Funktion schreiben, die beide Dateien einlesen kann. Wie kann ich das am besten machen?

Vielen Dank schonmal!!!
LG
F
-
Ich würde das ungefähr so machen:
struct data { data(double t_, double x_t_, double sigma_) : t(t_), x_t(t_), sigma(sigma_) { } double t; double x_t; double sigma; }; std::vector<data> read_data() { std::vector<data> data; std::ifstream input("in.txt"); std::string line; double t, x_t, sigma; while ( std::getline(input, line) ) { if ( line[0] != '#' ) { std::istringstream is(line); is >> t >> x_t >> sigma; data.emplace_back(t, x_t, sigma); } } return data; }
-
icarus macht es etwas umständlich. Ich schlage
#include <vector> #include <sstream> // Für Dateistreams fstream #include <limits> #include <iostream> struct data { double t; double x_t; double sigma; }; std::istream& operator>>( std::istream& is, data& d ) { return is >>d.t >>d.x_t >>d.sigma; } std::ostream& operator<<( std::ostream& os, data const& d ) { return os <<d.t <<d.x_t <<d.sigma; } int main() { /// Folgender Stream soll den Dateistream simulieren: std::istringstream stream { R"(# Kommentar # Kommentar # Kommentar # Kommentar 3020.81108 14.082 0.006 3021.83499 14.044 0.006 3023.69700 14.030 0.006 )" }; std::vector<data> data_vector; for (data d; stream >> std::ws;) { if (stream.peek() == '#') stream.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); else if (stream >> d) data_vector.push_back(d); else break; } for (auto const& d : data_vector) std::cout << d << '\n'; }vor.
-
Oder falls du weißt dass die Kommentare alle hintereinander ganz am Anfang stehen:
std::vector<data> data_vector; // Werner-Style while ((stream >> std::ws).peek() == '#') stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::copy( std::istream_iterator<data>{stream}, {}, std::back_inserter(data_vector) ); for (auto const& d : data_vector) std::cout << d << '\n';Zusätzlich noch die Header
<algorithm>und<iterator>einbinden.
-
Ich empfehle putback.
while(!in.eof()){ char c; // Testzeichen in >> c; if (c == '#') { in.ignore('\n', std::numeric_limits<std::streamsize>::max()); // ignoriere die Zeile continue; } in.putback(c); // lege das gelesene Zeichen zurück in>>t; in>>X_t; in>>sigma; dataset.push_back(vector<double>()); dataset[i].push_back(t);//Zeit dataset[i].push_back(X_t);//Signal dataset[i].push_back(sigma);//Signal i++; }
-
Vielen, vielen Dank für die Hilfe!!
Ich habe mich letztendlich für putback entschieden, da dies die Lösung ist, die ich am einfachsten nachvollziehen konnte.