Aus .txt Datei lesen
-
Stromberg schrieb:
bool file_input(string &file,const string input) { // … return 1; } return 0; }Was soll eigentlich der Unsinn, '0' und '1' statt 'false' und 'true' zu benutzen?
Und außerdem halte ich die Lösung mit 'getline' für absoluten Overkill, wenn es doch viel einfacher über einen Stream geht. Wir wollen schließlich keine Zeilen einlesen sondern die gesamte Datei. Wie ich bereits gepostet habe, geht das mit *einer Zeile*!
-
Ah du hast da ja was gepostet, hab ich gar nicht gelesen:
string read_file(string const& fname) { return dynamic_cast<stringstream*>(&(stringstream() << ifstream(fname.c_str()).rdbuf()))->str(); }Ah mit einer Zeile ist das ja noch einfacher....bloß muss ich mir das erst noch ma genau anschauen, weil auf die schnell blick ich das jetzt nicht, und was ist den bite ein "dynamic_cast"?
Und zu dem TRUE und FALSE noch, also ich hab irgendwo auf so einer Internetseite mal gelesen das es gar nicht gut sein soll "TRUE" und "FALSE" zu verwenden, des hat da irgendjemand gesagt..(vll. find ichs wieder).
Aber eigentlich benutze ich auch immer TRUE und FALSE...weiß eiegtnlich auch nicht warum ich jetzt 1 und 0 genommen habe.
Und was meinst du mit Overkill? Meinst damit das es zu lange dauert?
Dankeschön schon mal im Voraus.
-
Konrad Rudolph schrieb:
string read_file(string const& fname) { return dynamic_cast<stringstream*>(&(stringstream() << ifstream(fname.c_str()).rdbuf()))->str(); }da ostream keine virtuelle basisklasse von stringstream ist, kannst du dir den dynamic_cast sogar sparen.
-
Konrad Rudolph schrieb:
Was soll eigentlich der Unsinn, '0' und '1' statt 'false' und 'true' zu benutzen?
Was soll daran Unsinn sein ???
Konrad Rudolph schrieb:
string read_file(string const& fname) { return dynamic_cast<stringstream*>(&(stringstream() << ifstream(fname.c_str()).rdbuf()))->str(); }Wenn du deine eine Zeile haben willst, dann lieber sowas:
string fileText = string(istreambuf_iterator<char>(file),istreambuf_iterator<char>());
-
queer_boy schrieb:
Konrad Rudolph schrieb:
string read_file(string const& fname) { return dynamic_cast<stringstream*>(&(stringstream() << ifstream(fname.c_str()).rdbuf()))->str(); }da ostream keine virtuelle basisklasse von stringstream ist, kannst du dir den dynamic_cast sogar sparen.
Ne, kann ich nicht, denn 'operator<<' gibt mir nunmal keinen stringstream zurück sondern einen 'basic_ostream<…>'. Aber ein 'static_cast' reicht natürlich.
Stromberg schrieb:
Und zu dem TRUE und FALSE noch, also ich hab irgendwo auf so einer Internetseite mal gelesen das es gar nicht gut sein soll "TRUE" und "FALSE" zu verwenden, des hat da irgendjemand gesagt..(vll. find ichs wieder).
Stimmt auch, ich sprach aber von 'true' und 'false', nicht von 'TRUE' und 'FALSE'. 'true' und 'false' sind Bool-Konstanten, 1 und 0 hingegen sind Int-Konstante.
Und was meinst du mit Overkill? Meinst damit das es zu lange dauert?
Ich nehme an, dass es länger dauert aber das meinte ich nicht. Ich meinte, dass der Code einfach eine falsche Semantik vermittelt. Er suggeriert, dass hier Zeilen eingelesen werden. Overkill ist es deswegen, weil hier mehr Operationen stattfinden als nötig sind und das führt natürlich potentielle Fehlerquellen ein. Es widerspricht einfach dem Grundsatz, alles so einfach wie möglich zu halten.
Zu 'dynamic_cast': Hier wird zur Laufzeit geprüft, ob der Cast vollzogen werden kann. Sollte das nicht der Fall sein, wird 0 zurückgegeben.
-
Konrad Rudolph schrieb:
wird 0 zurückgegeben.
Und die 0 landet dann im string und es macht *boom*

Konrad Rudolph schrieb:
Ich nehme an, dass es länger dauert aber das meinte ich nicht. Ich meinte, dass der Code einfach eine falsche Semantik vermittelt. Er suggeriert, dass hier Zeilen eingelesen werden. Overkill ist es deswegen, weil hier mehr Operationen stattfinden als nötig sind und das führt natürlich potentielle Fehlerquellen ein. Es widerspricht einfach dem Grundsatz, alles so einfach wie möglich zu halten.
Hättest es ja auch vorher so schreiben können

-
KasF schrieb:
Konrad Rudolph schrieb:
Was soll eigentlich der Unsinn, '0' und '1' statt 'false' und 'true' zu benutzen?
Was soll daran Unsinn sein ???
Es vermittelt eine falsche Semantik. Wozu gibt's denn verschiedene Typen? Wenn man die nicht benutzt, muss man auch nicht C++ programmieren, dann reicht eine Sprache ohne Typen.
string fileText = string(istreambuf_iterator<char>(file),istreambuf_iterator<char>());Hm. Irgendwie hatte ich in Erinnerung, dass man hier erst ein Flag setzen müsste, damit Leerzeichen nicht überlesen werden.
Aber meine Methode ist schneller :p
-
Konrad Rudolph schrieb:
Es vermittelt eine falsche Semantik.
Das reicht mir schon als Argument. Überzeugt.
Konrad Rudolph schrieb:
Hm. Irgendwie hatte ich in Erinnerung, dass man hier erst ein Flag setzen müsste, damit Leerzeichen nicht überlesen werden.
Das macht das schöne buf am Ende von ifstreambuf

Konrad Rudolph schrieb:
Aber meine Methode ist schneller :p
Wohlmöglich ...
-
Konrad Rudolph schrieb:
queer_boy schrieb:
Konrad Rudolph schrieb:
string read_file(string const& fname) { return dynamic_cast<stringstream*>(&(stringstream() << ifstream(fname.c_str()).rdbuf()))->str(); }da ostream keine virtuelle basisklasse von stringstream ist, kannst du dir den dynamic_cast sogar sparen.
Ne, kann ich nicht, denn 'operator<<' gibt mir nunmal keinen stringstream zurück sondern einen 'basic_ostream<…>'. Aber ein 'static_cast' reicht natürlich.
war das nicht klar?
nur falls es dich interessiert, nicolai josuttis ist deiner meinung, was die geschwindigkeit der lösungen anbelangt
außer der string-konstruktor schafft es, extrem gut mit iteratoren (streambuf iteratoren) umzugehen.
-
queer_boy schrieb:
Konrad Rudolph schrieb:
Aber ein 'static_cast' reicht natürlich.
war das nicht klar?
Nein, aber Du hast recht: Es hätte mir klar sein können. *deng*
nicolai josuttis ist deiner meinung, was die geschwindigkeit der lösungen anbelangt

Das freut mich – wobei es mich ehrlich gesagt aber wundert (ich hab's erst nach Performance-Tests geglaubt). Der string-Konstruktor müsste doch in der Lage sein, genauso wie der stringstream einen dynamisch wachsenden Buffer zu verwenden und die Daten blockweise einzulesen. Oder übersehe ich da irgendwas?
-
string könnte in der tat schneller sein, wenn es die segmented sequence optimization verwenden würde*. das problem ist, dass die iteratoren intern ständig checken, wieviel noch im buffer ist (direkt oder indirekt via sbumpc) und ohne eine blockorientierte spezialisierung ist das schwer wegzuoptimieren. das problem hast du mit dem stringstream und dem buffer nicht, weil der sich das ganze tatsächlich geblockt einliest. (übrigens tritt dasselbe problem auf mit deque, weil deque auch blockorientiert arbeitet)
*(die implementierung von gcc 4.1.2 ist sogar tatsächlich schneller, wenn die datei eine bestimmte größe unterschreitet, weil sie intern einen fixen buffer verwendet)
-
queer_boy schrieb:
(übrigens tritt dasselbe problem auf mit deque, weil deque auch blockorientiert arbeitet)
Das finde ich interessant: Warum sollte die Deque mit Segmenten arbeiten? Ich kenne nur die naiven Implementierungen einer Deque als doppelt verkettete Liste oder als Ringpuffer. Wie funktioniert das mit Segmenten? Ich habe über Google auf die Schnelle keine Informationen finden können.
-
nicht notwendigerweise, weil middle-insert nicht in O(1) arbeiten muss. kann ich jetzt leider nicht zitieren. (aber nicht umsonst bietet deque random-access an, anders als list)
die deque aus der gcc-stl macht es z.b. so:
//deque::iterator::operator+= Self& operator+=(difference_type n) { const difference_type offset = n + (cur - first); if (offset >= 0 && offset < buffer_size()) cur += n; else { const difference_type node_offset = offset > 0 ? offset / buffer_size() : -((-__offset - 1) / buffer_size()) - 1; set_node(node + node_offset); cur = first + (offset - node_offset * buffer_size()); } return *this; }die nodes sind die blöcke, von denen ich sprach. ob die als doppelt verlinkte liste implementiert werden oder nicht, ist ziemlich egal für meine aussage.
-
queer_boy schrieb:
nicht notwendigerweise, weil middle-insert nicht in O(1) arbeiten muss.
Eben (steht in 23.2.1.1). Wo ist da also der Vorteil der Segmente gegenüber dem Vektor-Ringpuffer? Ich mag mich irren aber mir kommt es von der Intuition her so vor, als habe der Ringpuffer ein besseres Laufzeitverhalten. Das mag aber daran liegen, dass mir immernoch nicht ganz klar ist, wie die Struktur genau aussehen soll. Ich meine, wie werden die Segmente Verwatltet? Wie funktioniert ein push_front?
– Aber Danke für Deine Infos, ich schaue mir das nachher einfach mal in den GCC-Standardheadern an, da sollte das ja drinstehen.