Elegant ein ganzes File einlesen?
-
Danke. Ist zwar schöner als meins, hat aber das gleiche Problem: Newlines werden verschluckt.
EDIT: Nicht nur newlines, sondern überhaupt jeglicher whitespace.
-
Du musst binär auslesen um wirklich sämtliche Daten aus einer Datei zu erhalten.
MfG SideWinder
-
#include <iterator> std::string readfile(std::string const & filename) { std::ifstream f(filename.c_str() , std::ios::binary ); // das std::ios::binary // ist hier wichtig, unter Linux sollte das keine auswirkung haben, aber unter // Windows ist das erforderlich damit auch wirklich alle Zeichen gelesen werden. //EDIT: Wenn es sich um nicht anzeigbare Zeichen wie z.b. 0x00 handelt. Whitespaces werden auch ohne ios::binary ausgelesen char buf[512] = {0}; std::size_t len = 0; std::string value; while(len = f.read(buf,512).gcount()) // gcount() gibt hier die anzahl der gelesenen Zeichen zurück value += std::string(buf,len); return value; }
-
evilissimo: es ging um eleganz.
-
Hinweis... schrieb:
evilissimo: es ging um eleganz.
stimmt auch wieder, hab nicht aufgepasst
-
Hallo,
Variante 1:#include <string> #include <fstream> #include <iterator> int main() { std::ifstream file("main.cpp"); std::string s((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); }
Achtung: Die Extraklammern um den ersten Parameter des Ctors von s sind wichtig.
Variante 2:
#include <string> #include <fstream> #include <iterator> int main() { std::ifstream file("deineDatei.txt"); file.unsetf(std::ios_base::skipws); std::string s((std::istream_iterator<char>(file)), std::istream_iterator<char>()); }
Variante 3:
#include <string> #include <fstream> #include <iterator> int main() { std::ifstream file("main.cpp"); std::stringstream str; str << file.rdbuf(); std::string s(str.str()); }
-
Hi,
HumeSikkins schrieb:
Achtung: Die Extraklammern um den ersten Parameter des Ctors von s sind wichtig.
Könntest Du auch erklären, wieso? Wäre toll.
-
Könntest Du auch erklären, wieso? Wäre toll.
Das ist mir auch nicht ganz geheuer. Bei mir geht's jedenfalls auch ohne. Ist mir auch nicht aufgefallen beim Abtippen - wer schaut denn auf sowas?
Wow, 1 und 3 gefallen mir sehr :D. Ich hab ja gewusst, dass es gehen muss... Danke!
-
Konrad Rudolph schrieb:
Hi,
HumeSikkins schrieb:
Achtung: Die Extraklammern um den ersten Parameter des Ctors von s sind wichtig.
Könntest Du auch erklären, wieso? Wäre toll.
Ohne die extra Klammern ist das:
std::string s(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
kein Definition eines String-Objekts s sondern die Deklaration einer Funktion namnes s die einen string liefert und zwei Parameter erwartet.
Der erste Parameter ist vom Typ std::istreambuf_iterator<char> und hört auf den Namen file (die Klammern um file werden einfach ignoriert).
Der zweite Parameter, der keinen formalen Namen hat, ist vom Typ Funktion die
keine Parameter erwartet und einen einen std::istreambuf_iterator<char> liefert.Warum das so ist? In C++ gilt die Regel, dass eine Zeile, die als Funktionsdeklaration geparsed werden kann auch eine Funktionsdeklaration ist.
Das bekannteste Beispiel für diese Mehrdeutigkeit ist die falsche Verwendung eines Default-Ctors:string s();
Hier wird ja ebenfalls kein Objekt definiert sondern eine Funktion s deklariert, die keine Parameter erwartet und einen std::string liefert.
Durch die Extraklammern um den ersten Parameter kann die Zeile nicht mehr als Funktionsdeklaration geparsed werden, da formale Parameter nicht mit Klammern umrundet werden dürfen. Auf der anderen Seite dürfen Funktionsargumente hingegen aber ruhig eingeklammert werden.
Sprich:
void f(int); // ok void f( (int) ); // Syntaxfehler // aber f(1); // ok f( (1) ); // ok f( ((1)) ); // ok
-
Not bad! Ich dachte, ich kenn mich mit C++ gut aus, aber das ist mir jetzt echt neu ;).
EDIT: Ich hab mich sogar vor ein paar Wochen darüber gewundert, warum ein Stück Code nicht compilieren wollte. Ich habe es auf den buggy Borland-Compiler geschoben, aber jetzt wurde ich eines besseren beleert...