Problem beim Einlesen einer Datei: string in Variable
-
Hallo,
Eine Fehlerbeschreibunge wäre nich schlecht.
aber mal sehen.
Nach dem getline liest du nochmal vom File. da ist er aber schon in der nächsten Zeile wo keine Zahlen mehr stehen. Versuchs mal soif (line.find(" on ") != string::npos) { stringstream sstr(line); sstr >> a >>b >> c >> d; }
-
Weil auch ich gerade Zeit hatte, mein Lösungsvorschlag. Ansonsten kann ich mich meinen Vorrednern nur anschließen:
#include<iostream> #include<fstream> #include<sstream> #include<string> using namespace std; struct ABCD { double a; double b; double c; double d; }; bool hasOn(const string& line); ABCD getABCDfromFile(const string& filename); int main(int argc, char** args) { ABCD foo = getABCDfromFile("test.txt"); cout << " a: " << foo.a << " b: " << foo.b << " c: " << foo.c << " d: " << foo.d << endl; return 0; } ABCD getABCDfromFile(const string& filename) { ifstream infile(filename.c_str()); string line; ABCD abcd; while(getline(infile, line)) { if(hasOn(line)) { stringstream stream(line); stream >> abcd.a >> abcd.b >> abcd.c >> abcd.d; } } return abcd; } bool hasOn(const string& line) { return (line.find(" on") != string::npos); }Ich habe mich hier für ein struct (und damit gegen einen std::vector<double>) entschieden, da die Struktur der Daten in der Textdatei bekannt ist (zu sein scheint) - ich hoffe einfach mal, dass ich es mit der Refaktorisierung nicht all zu sehr auf die Spitze getrieben, aber das hilft mir beim Denken.
Grüße aus dem S(ch)auerland
Heiko
-
Wenn du deiner struct noch einen operator>> spendierst geht das Einlesen noch leichter.
-
Braunstein schrieb:
Wenn du deiner struct noch einen operator>> spendierst geht das Einlesen noch leichter.
Ich bin noch nicht so lange dabei, deswegen interessiert mich der Lösungsansatz nun. Mit dem Überladen von Operatoren im Kontext der Streams habe ich mich bis dato noch gar nicht beschäftigt. Sieht aber vielversprechend aus.
Hier mein Ansatz:
Prototyp:
void operator>>(istream& in, ABCD& out);Definition:
void operator>>(istream& in, ABCD& out) { in >> out.a >> out.b >> out.c >> out.d; }Aufruf:
stream >> abcd;Im Grunde war das nur ein Schuss ins Blaue - das Programm funktioniert zumindest, wie erwünscht
.Grüße aus dem S(ch)auerland aus einer Wolkenlücke
Heiko
-
Fast, die Signatur ist etwas anders.
istream& operator>>(istream& in, ABCD& out);Jetzt kann man die Operatoren auch verketten.

-
<klugscheiss>Was voraussetzt, dass die Funktionsdefinition eben auch wieder eine Referenz auf istream zurück gibt...:</klugscheiss>
istream& operator>>(istream& in, ABCD& out) { in >> abcd.a >> abcd.b >> abcd.c >> abcd.d; return in; }... man, schon wieder was gelernt ...

-
bwbg schrieb:
<klugscheiss>Was voraussetzt, dass die Funktionsdefinition eben auch wieder eine Referenz auf istream zurück gibt...:</klugscheiss>
Wieso hier <klugscheiss>Modus? Das war doch klar.

-
dann auch streamoperator << überladen ... man sollte auch vorher gucken ob die Zeile mit # anfängt ... das sollen ja Kommentare sein 
#include <iostream> #include <fstream> #include <sstream> #include <string> struct values { double a; double b; double c; double d; values(double a = 0, double b = 0, double c = 0, double d = 0) : a(a), b(b), c(c), d(d) {} }; std::istream& operator>>(std::istream& in, value& val) { in >> a >> b >> c >> d; return in; } std::ostream& operator<<(std::ostream& in, value& val) { in << a << " " << b << " " << c << " " << d; return in; } values get_values_f(const std::string&); int main() { std::cout << get_values_f("data.abc") << std::endl; } values get_values_f(const std::string& filename) { std::ifstream infile(filename.c_str()); std::string line; while (std::getline(infile, line)) { if (line.at(0) != '#' && line.find(" on ") != std::string::npos) { std::ostringstream ss(line); values data; ss >> data; return data; } } return values(); }...
-
1.) getline ist doof
2.) was ist eigentlich, wenn in '# Irgendein Text' ein "on" vorkommt?#include <iostream> #include <fstream> #include <string> #include <iterator> // istream_iterator #include <functional> // mem_fun_ref #include <limits> // numeric_limits #include <algorithm> // find_if struct ABCD { double a; double b; double c; double d; bool m_on; bool On() const { return m_on; } }; // -- Kommentar überlesen std::istream& comment( std::istream& in ) { using namespace std; if( in >> ws ) // ggf. letztes Zeilenende überlesen { // -- falls das nächste Zeichen ein '#' ist, überlese die Zeile typedef istream::traits_type traits_type; while( traits_type::eq_int_type( in.peek(), traits_type::to_int_type('#') ) ) in.ignore( numeric_limits< streamsize >::max(), '\n' ); } return in; } // -- Einlesen von ABCD std::istream& operator>>( std::istream& in, ABCD& abcd ) { ABCD out; std::string on_off; if( in >> comment >> out.a >> out.b >> out.c >> out.d >> on_off ) { if( on_off == "on" || on_off == "off" ) { out.m_on = (on_off == "on"); abcd = out; // lesen ok; wert übernehmen } else // Lesefehler; 5. Wert ist weder 'on' noch 'off' in.setstate( std::ios_base::failbit ); } return in; } // -- Ausgeben von ABCD std::ostream& operator<<( std::ostream& out, const ABCD& abcd ) { return out << abcd.a << " " << abcd.b << " " << abcd.c << " " << abcd.d; } int main() { using namespace std; ifstream quelle( "test.txt" ); if( !quelle.is_open() ) { cerr << "Fehler beim Oeffnen der Datei" << endl; return -1; } istream_iterator< ABCD > i = find_if( istream_iterator< ABCD >( quelle ), istream_iterator< ABCD >(), mem_fun_ref( &ABCD::On ) ); if( i != istream_iterator< ABCD >() ) cout << "Gefunden: " << *i << endl; return 0; }Gruß
Werner
-
Zu 2.) Dann ist line.at(0) == '#' ...
Hast aber natürlich recht ... so geht es auch ... ist aber etwas umständlicher ... hast natürlich noch nen bissel mehr Fehlerbehandlung drin ...