Aus .txt Datei lesen
-
Also vielen Danke erst mal an dich KasF für deine lange Erklärung.
Ich hab mich jetzt nochmal genau hingesetzt, und das von (D)Evil und von dir aufmerksam durchgelesn, bisschen rumprobiert, wieder euren Code angeschaut.... und ich bilde mir ein es nun verstanden zu haben. Das hier wäre mein Code:#include <iostream> #include <fstream> #include <string> using namespace std; int file_volume(ifstream &stream); bool file_input(string &file,const string input) ; int main() { string buffer; file_input(buffer,"D:\\Hans.txt"); cout << buffer << endl; return 0; } int file_volume(ifstream &stream) { int temp; if(stream) { stream.seekg(ios::beg,ios::end); temp=stream.tellg(); stream.seekg(ios::beg); } else { return 0; } } bool file_input(string &file,const string input) { ifstream data(input.c_str()); string temp; while(getline(data,temp)) { file=file+temp+"\n"; } if(file.length()!=file_volume(data)) { data.close(); return 0; } data.close(); return 1; }Jetzt is es aber doch ganz in Ordnung, is ja so ähnlich wie euer Code?
Das mit dem "while(getline(data,temp))...." was du mir erklärt hast KasF, ist natürlich schon n kleiner unterschied zu dem was ich gemacht habe
Dankeschön schon mal im Voraus.
-
hmm ...
stream.seekg(ios::beg,ios::end);... was soll das sein? Guck dir mal die genaue Deklaration von seekg an ... http://www.cppreference.com/cppio/seekg.html
int file_volume(ifstream &stream) // warum int? kann doch nur positiv lang sein ;) => std::size_t (meist das selbe wie unsigned int) { int temp; // warum hier schon anlegen? Wird doch nur genutzt wenn stream geöffnet ist ... if(stream) { stream.seekg(ios::beg,ios::end); // s. o. temp=stream.tellg(); // hmm tellg sollte aber std::streampos und nicht int zurückgeben. stream.seekg(ios::beg); // Und wenn du vorher nicht am Anfang der Datei warst? } else { return 0; } }...
bool file_input(string &file,const string input) { ifstream data(input.c_str()); // und was ist wenn du die Datei nicht öffnen konntest? (!data) // Was ist wenn in file schon was drin steht? string temp; while(getline(data,temp)) { file=file+temp+"\n"; } if(file.length()!=file_volume(data)) // wofür?! { data.close(); // unnötig ... return 0; } data.close(); // unnötig ... return 1; }
-
Zudem von (D)Evil noch. file_volume vergisst einmal was zurückzugeben

-
Joa, so gut isses anscheinend noch nicht, aber es ist besser als mein anfang.
Zu dem hier noch:if(file.length()!=file_volume(data)) // wofür?! { data.close(); // unnötig ... return 0; } data.close(); // unnötig ... return 1;Ich will doch 0 zurückgeben wenn es fehlgeschlagen hat und 1 zurückgeben wenn es funktioniert hat? Aber vll. ist das von mir n bissel komisch umgesetzt worden?
Was ist wenn in file schon was drin steht?
Das ist doch egal oder? Dann wird das halt einfach überschrieben und es steht halt was neus drin?
Dakeschön schon mal im Voraus.
-
#include <iostream> #include <fstream> #include <string> using namespace std; //int file_volume(ifstream &stream); bool file_input(string &file,const string input) ; int main() { string buffer; file_input(buffer,"D:\\Hans.txt"); cout << buffer << endl; return 0; } /*size_t file_volume(ifstream &stream) { if(stream) { int temp; stream.seekg(ios::beg,ios::end); temp=stream.tellg(); stream.seekg(ios::beg); } else { return -1; } }*/ bool file_input(string &file,const string input) { ifstream data(input.c_str()); if(data.is_open()) { string temp; while(getline(data,temp)) { file=file+temp+"\n"; } data.close(); return 1; } return 0; }Wie is es so? Habs nochmal überdacht!
eigentlich brauch ich jetzt die "file_volume" Funktion doch nicht mehr oder? Äh und was passt an meiner "file_volume" den nicht, die funktiuoniert doch prima? Wie funktioniert das den sonst mit dem "seekg"? Ich kann mit dem Link irgendwie nicht viel anfangen, da stand nicht grad viel drin...?
Dankeschön schon mal im Voraus.
-
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.