Formatiert aus Datei lesen
-
Ich denke, wir haben/hatten dieselbe Frage:

http://www.c-plusplus.net/forum/293240
bzw. sogar noch passender
http://www.c-plusplus.net/forum/293076
-
Ich möchte Datensätze, jeweils beendet durch ein Newline-Zeichen ('\n').
Jeder Datensatz besteht aus zwei Strings und einem Integer, jeweils getrennt durch ein Space(' '). Nun möchte ich die Strings in zwei Instanzen vonstringund die Zahl in einenintspeichern. Aber außer der C-Lösung (fscanf(datei, "%s %i %s", s1, i, s2);(oder anders (ich habe nie viel C programmiert
)) fällt mir nichts ein...mfg D3lta
EDIT: zu langsam

Dank deinem Thread habe ich eine Idee
Aber gibt es wirklich keine einfachere Lösung in C++?
-
std::string s1, s2; int i; while(file >> s1 >> i >> s2) { // tu was damit }
-
314159265358979 schrieb:
std::string s1, s2; int i; while(file >> s1 >> i >> s2) { // tu was damit }Habe ich auch schon erfolglos probiert...
Dennoperator>>liest nur bis zu whitespaces...mfg D3lta
P.S.: So sollte es gehen, oder?
string s1, s2; int i; char c; char cs[20]; fstream f; while(!f.eof()) { f >> c; //erstes '"' überlesen f.getline(cs, '"'); //ürsprünglich f.getline(s1, '"'); s1=cs; f >> c; //' ' überlesen f >> i; f >> c >> c; //' ' und '"' überlesen f.getline(cs, 20, '"'); //ürsprünglich f.getline(s2, '"'); s2=cs; }EDIT:
getline()ist ja garnicht fürstringüberladen
, ich habe es kurz korrigiert 
EDIT2: Es funktioniert immer noch nicht...
-
D3lta schrieb:
EDIT:
getline()ist ja garnicht fürstringüberladen
, ich habe es kurz korrigiert 
-
Danke, mit
getline(f, s1, '"');funktioniert er auch fast, wie ich will.
mfg D3lta
EDIT: Problem gelöst

Hier ist der finale Code, falls irgendjemand noch einmal diesen Thread findet:while(!f.eof()) { f >> c; //erstes '"' überlesen getline(f, s1, '"'); f >> i; f >> c;'"' überlesen getline(f, s2, '"'); cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl; }Danke an alle, die mir geholfen haben, oder es versucht haben.

-
while(!f.eof())ist trotzdme noch falsch. Es muss
while(f)heißen

-
314159265358979 schrieb:
while(!f.eof())ist trotzdme noch falsch. Es muss
while(f)heißen

Warum?
Es funktioniert auch mit!f.eof().
Und gibt es eine noch kürzere oder einfachere Lösung?mfg D3lta
-
Weil du bei einem Lesefehler sonst in eine Endlosschleife kommst.
Und "funktioniert" ist nicht gleich funktioniert.
-
Was machst du eigentlich, wenn in deiner Datei eine Zeile vorkommt, die nicht genau deinem geparsten Format entspricht? Z.B. eine Leerzeile?
-
Falsch kann es nicht dem Sinne nicht sein.
-
Wutz schrieb:
Was machst du eigentlich, wenn in deiner Datei eine Zeile vorkommt, die nicht genau deinem geparsten Format entspricht? Z.B. eine Leerzeile?
Die Leerzeile hat das Programm erfolgreich pariert
.
Und für die anderen Fälle müsste man nach jedem Lesen überprüfen, ob ein Bit gesetzt ist?
Ungefähr so?:if(!f) break;314159265358979 schrieb:
Weil du bei einem Lesefehler sonst in eine Endlosschleife kommst.
Und "funktioniert" ist nicht gleich funktioniert.Gibt
ffalsezurück, wenn irgendein Bit, wie zum Beispieleof, gestzt ist?mfg D3lta
-
D3lta schrieb:
Gibt
ffalsezurück, wenn irgendein Bit, wie zum Beispieleof, gestzt ist?Ja! (genauer gesagt Null oder nicht-Null)
Und außerdem geben die ganzen Einlesefunktionen die Streams selber zurück. Das kann man sowohl nutzen, um die Streams direkt auszuwerten oder um weitere Lesefunktionen auf sie anzuwenden.
Und mit diesen beiden Eigenschaften der Streams kann man die ganzen schönen Einleseschleifen bauen, wie man sie hier im Forum (und in guten Büchern) immer sieht. Super kurz, super robust, super mächtig, super sorgenfrei. Mit den anderen Varianten macht man sich bloß selber das Leben schwer.
-
SeppJ schrieb:
D3lta schrieb:
Gibt
ffalsezurück, wenn irgendein Bit, wie zum Beispieleof, gestzt ist?Ja! (genauer gesagt Null oder nicht-Null)
Und außerdem geben die ganzen Einlesefunktionen die Streams selber zurück. Das kann man sowohl nutzen, um die Streams direkt auszuwerten oder um weitere Lesefunktionen auf sie anzuwenden.
Und mit diesen beiden Eigenschaften der Streams kann man die ganzen schönen Einleseschleifen bauen, wie man sie hier im Forum (und in guten Büchern) immer sieht. Super kurz, super robust, super mächtig, super sorgenfrei. Mit den anderen Varianten macht man sich bloß selber das Leben schwer.
Dann ist mein Buch wohl wirklich kein gutes Buch...

Ist der Code dann so besser?while(f) { f >> c; //erstes '"' überlesen if(!f) break; getline(f, s1, '"'); if(!f) break; f >> i; if(!f) break; f >> c;'"' überlesen if(!f) break; getline(f, s2, '"'); if(!f) break; cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl; }mfg D3lta
P.S.: (Etwas weg vom Thema
) Gibt es hierfür eine Lösung?typedef vector<A*> AptrV; class A { private: AptrV aptrv; //... }Also ich will ein typedef einer Klasse global definieren, es aber in der Klasse verwenden. Mir fällt nichts ein, womit man das Problem lösen kann...
-
D3lta schrieb:
Ist der Code dann so besser?
Kommt es dir besser vor? Besser als vorher vielleicht. Gut? Ich denke mal nicht.
while(f) { f >> c; //erstes '"' überlesen if(!f) break; getline(f, s1, '"'); if(!f) break; f >> i; if(!f) break; f >> c;'"' überlesen if(!f) break; getline(f, s2, '"'); if(!f) break; cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl; }1. Wieso prüfst du nach jeder einzelnen Leseaktion? Wenn ein Fehler auftritt, wird sowieso nicht weitergelesen. Das kann man also äquivalent schreiben als:
while(f) { f >> c; //erstes '"' überlesen getline(f, s1, '"'); f >> i; f >> c;'"' überlesen getline(f, s2, '"'); if(!f) break; cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl; }2. Wie dir schon gesagt wurde, kann man Lesefunktionan auch aneinander hängen. Immer noch 100% äquivalent zu deinem vorherigen Code:
while(f) { getline((getline(f >> c, s1, '"') >> i >> c), s2, '"'); if(!f) break; cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl; }Über diese "Vereinfachung" kann man streiten, da es doch recht schwer zu lesen ist. Aber es macht das nächste einfacher:
3. Was soll der Unsinn mit dem while(f) und break? Du scheinst überhaupot nicht verstanden zu haben, was man dir hier im Thread erklären wollte. Wann bitte sollte f in der while-Bedingung jemals false sein (außer eventuell vor dem ersten Eintritt)? Genausogut hättest du auch while(true) scheiben können. Worauf man hier im Thread hinaus will, ist dies:
while(getline((getline(f >> c, s1, '"') >> i >> c), s2, '"')) cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;Da. Macht immer noch genau das gleiche wie vorher. Die while-Bedingung liest die Werte ein, geht was schief, wird abgebrochen, ansonsten geht's in die Ausgabe.
Wenn du nun noch eine hübsche Klasse für deine Daten definierst mit einem schönen Einleseoperator der alles schön kapselt, dann ist die while-Bedingung auch nicht mehr so ein Monstrum, sondern würde eher so aussehen:
// Oben werden ein paar Klassen und Funktionen definiert while(f >> dein_datenobjekt) cout << dein_datenobjekt << endl;Und jetzt vergleich das mal zu dem was du ursprünglich hattest. Und dann kann man auch die Frage beantworten: Besser? Ja! Gut? Ja!
P.S.: (Etwas weg vom Thema
) Gibt es hierfür eine Lösung?typedef vector<A*> AptrV; class A { private: AptrV aptrv; //... }Also ich will ein typedef einer Klasse global definieren, es aber in der Klasse verwenden. Mir fällt nichts ein, womit man das Problem lösen kann...
Forward-Deklaration?
-
Gut so ist es viel einfacher...

Und was ist Forward-Deklaration?mfg D3lta
-
D3lta schrieb:
Und was ist Forward-Deklaration?
Wenn man dem Compiler beschewid sagt, daß es eine Klasse später gibt. Dann kann er schonmal Zeiger auf A machen und A als Referenz, Funktionsparameter oder Rückgabe verwenden.
class A;//nur bescheid gesagt typedef vector<A*> AptrV;//Deswegen geht A* hier schon. class A //Definition nachgeholt { private: AptrV aptrv; //... };
-
volkard schrieb:
D3lta schrieb:
Und was ist Forward-Deklaration?
Wenn man dem Compiler beschewid sagt, daß es eine Klasse später gibt. Dann kann er schonmal Zeiger auf A machen und A als Referenz, Funktionsparameter oder Rückgabe verwenden.
class A;//nur bescheid gesagt typedef vector<A*> AptrV;//Deswegen geht A* hier schon. class A //Definition nachgeholt { private: AptrV aptrv; //... };Danke, ich hatte es schon einmal probiert, aber ich habe keine Ahnung, was ich da falschgemacht hatte.

Ich kannte das bisher nur von Funktionen...mfg D3lta