Struct in Datei schreiben aus CodeGuru.com
-
Sowas nennt man dann inkonsistent
Und inwiefern ist das schlecht?
VarInts koennen genau dasselbe, nur besser.
Pauschal: Völliger Blödsinn.
-
SeppJ schrieb:
@Darkshadow44: Deine Argumentation ist komisch. Erst einmal die Fakten:
-Mit size_t ist das Programm immer richtig.
-Mit einem anderen Typen manchmal nicht.Nur in Fällen in denen ein massives Designproblem vorliegt. Niemand braucht einen std::string größer als 4GB!
SeppJ schrieb:
Wie kannst du da ernsthaft für die anderen Typen argumentieren?
Ich sagte ja nicht dass int oder uint32_t besser als size_t wäre.
Klar kannst du auch size_t nehmen, wenn du explizit strings >4GB erlauben willst.
Halte ich allerdings nicht für nötig und würde ich einfach verbieten.
Wenn du es allerdings explizit erlauben willst, dann würde ich zu uint64_t statt size_t tendieren. Dann können auch z.B. 32Bit Programme die Länge der großen Strings einlesen und dann einen Fehler ausgeben statt Mist zu bauen.
-
DarkShadow44 schrieb:
Niemand braucht einen std::string größer als 4GB!
Und was ist mit sicheren Passwörtern?
-
Du definierst den Fall, in dem deine Methode ohne triftigen Grund(!)* versagt, einfach zum Designproblem? Niemand braucht Strings über 4GB? Niemand braucht mehr als 640kB RAM? Niemand braucht Zuhause einen Computer? Niemand wird je Videos aus dem Internet gucken?
*: Dies ist das Verwirrendste von allen. Alle Probleme wären mit einem Schlag gelöst, wenn size_t statt einem anderen Typen genommen würde. Eine einzige Änderung an einer einzigen Stelle, der sonstige Code wäre identisch. Wieso diese Gegenwehr?
-
Mechanics schrieb:
Und was ist mit sicheren Passwörtern?
Die sind keine 4GB ?
SeppJ schrieb:
Du definierst den Fall, in dem deine Methode ohne triftigen Grund(!)* versagt, einfach zum Designproblem?
Fehlerbehandlung fehlt in beiden Varianten, sei es nun die Größe des strings oder ein EOF. Muss man naürlich auch noch einbauen.
SeppJ schrieb:
Niemand braucht mehr als 640kB RAM? Niemand braucht Zuhause einen Computer? Niemand wird je Videos aus dem Internet gucken?
Als ob das vergleichbar wäre.
Bei Arrays sehe ichs ja noch ein, aber definitiv nicht für std::string.
Wie gesagt, wenn du unbedingt 4GB strings willst (was auch immer du mit diesem Monster willst), dann nimm uint64_t:DarkShadow44 schrieb:
Dann können auch z.B. 32Bit Programme die Länge der großen Strings einlesen und dann einen Fehler ausgeben statt Mist zu bauen.
Dann hast du es wenigstens Konsistent, und Nachteile hat das nicht.
-
Ich zitiere noch einmal die Frage, vor der du dich die ganze Zeit drückst:
Alle Probleme wären mit einem Schlag gelöst, wenn size_t statt einem anderen Typen genommen würde. Eine einzige Änderung an einer einzigen Stelle, der sonstige Code wäre identisch. Wieso diese Gegenwehr?
Nenne einen Grund, nicht immer size_t zu nehmen. Einen einzigen! Du hast 0 Nachteile durch size_t, der Code ist identisch! Bei allen anderen Typen hast du eine künstliche Unportabilität und/oder Grenze eingebaut. "inkonsistent", "mag ich nicht", "niemand braucht das", sind alles nur Strohmannargumente. Wo ist der sachliche Grund, nicht size_t zu nutzen?
Bei Arrays sehe ichs ja noch ein, aber definitiv nicht für std::string.
Und womit speicher ich mein OTP? vector<char>, obwohl's doch eine Zeichenkette ist? Wie speicherst du vector<char> ab? Auf einmal doch mit size_t?
Dann können auch z.B. 32Bit Programme die Länge der großen Strings einlesen und dann einen Fehler ausgeben statt Mist zu bauen.
Seit wann können 32-Bit Programme nicht erkennen, ob eine Zahl größer oder kleiner ist als eine andere? Wo ist der Unterschied, wenn man da uint32_t oder size_t als Datentyp benutzt? Die Fehlerbehandlung fehlt bei deinem momentanen Code sowieso, aber sie wäre in beiden Fällen immer noch gleich.
Was ist mit 16-Bit Programmen?
-
Als ob das vergleichbar wäre.
Und ob.
Dann können auch z.B. 32Bit Programme die Länge der großen Strings einlesen und dann einen Fehler ausgeben statt Mist zu bauen.
uint64_t
kann größer sein alssize_t
. Und dastd::string::size_type
praktisch immer ein Typedef aufsize_t
ist wirste da irgendwo einen Überlauf kriegen - aber ohne es zu sehen.std::istream::operator>>
würde aber beisize_t
- falls die Länge zu groß ist als dass sie reinpasst - in den Fehlerzustand gehen. Das würde das Programm (hoffentlich) registrieren und den Fehler behandeln.Vorteil
size_t
: Ist die Länge zu groß für die Lese-Platform merkt das Programm es durch den Fehlerzustand des Streams.
Nachteiluint64_t
: Du merkst ohne weiteres nicht dass die Länge zu groß ist. Das Programm wird irgendeinen Schabernack treiben. Sollen wir jedes mal wenn wir deinenuint64_t
einlesen explizit prüfen ob er nicht in einenstd::string::size_type
passt? Sogar wenn der Stream-Operator es für uns tun könnte?Niemand braucht einen
std::string
größer als 4GBIch brauche einen
std::string
größer als 4 GiB (bitte Binärpräfixe nutzen), deine These ist widerlegt.und Nachteile hat das nicht.
Ein Leser deines Codes wird sich fragen warum zum Teufel du
uint64_t
für die Länge verwendest, denn deine Argumentation wird er nie im Leben nachvollziehen können (zumal sie glücklicherweise nicht bekannt ist).
-
Ich stimme mal DarkShadow44 zu. Ihr habt doch alle einen an der Waffel.
-
Kellerautomat schrieb:
Ich stimme mal DarkShadow44 zu. Ihr habt doch alle einen Finderabdruck an der essbaren Waffel.
Irgendwann wirst Du dabei noch erwischt, wie Du Flüßigkeit in den Briefkasten schüttest und dann klicken die Hanschellen....
-
Kellerautomat schrieb:
Ich stimme mal DarkShadow44 zu. Ihr habt doch alle einen an der Waffel.
Wenn weiter so sachlich argumentiert wird, kann ich den Thread auch schließen. Möchtest du nicht noch sagen, dass wir hässlich sind und daher keiner Ahnung haben? Oder uns mit Hitler vergleichen?
-
SeppJ schrieb:
Wenn weiter so sachlich argumentiert wird, kann ich den Thread auch schließen.
Was soll ich dazu sagen? Du kommst doch hier mit so nem formatiert/binaer-Mischmasch der die Nachteile von beidem vereint.
Und dann ist dann noch Hacker, der es skandaloes findet, dass es Leute gibt, die mit Strings <4GB auskommen. Unfassbar, verbrennt sie!Splitte den Thread am besten oder so.
SeppJ schrieb:
Möchtest du nicht noch sagen, dass wir hässlich sind und daher keiner Ahnung haben? Oder uns mit Hitler vergleichen?
Keine Ahnung was das jetzt sein soll. Aber wo du schon danach fragst: Hacker spreche ich in der Tat einige Kompetenzen ab. Er hat in der Vergangenheit schon oft genug bewiesen, dass er keinen Plan hat und sein Verhalten hier bestaetigt das nur ein weiteres Mal.
Was bei dir los ist, weiss ich nicht :p
-
Kellerautomat schrieb:
Er hat in der Vergangenheit schon oft genug bewiesen, dass er keinen Plan hat und sein Verhalten hier bestaetigt das nur ein weiteres Mal.
Man könnte meinen du spricht über dich selbst.
-
hustbaer schrieb:
Man könnte meinen du spricht über dich selbst.
Keine Ahnung wovon du sprichst, ich hab eigentlich bisher mit relativ wenigen Leuten Probleme gehabt.
-
Er hat in der Vergangenheit schon oft genug bewiesen, dass er keinen Plan hat und sein Verhalten hier bestaetigt das nur ein weiteres Mal.
lol.
Was bei dir los ist, weiss ich nicht
Sobald jemand den du für kompetenter als dich selbst hältst deine Meinung nicht teilt verstehst du die Welt nicht mehr?
Ist nichts neues.
Und dann ist dann noch Hacker, der es skandaloes findet, dass es Leute gibt, die mit Strings <4GB auskommen.
Nein, ich halte es nur für angebracht dass der einzige Fall indem Unterschiede der beiden Methoden vorliegen berücksichtigt wird. Und es einfach zu leugnen ist völlig bescheuert.
-
Kellerautomat schrieb:
SeppJ schrieb:
Wenn weiter so sachlich argumentiert wird, kann ich den Thread auch schließen.
Was soll ich dazu sagen? Du kommst doch hier mit so nem formatiert/binaer-Mischmasch der die Nachteile von beidem vereint.
WTF?
DarkShadow44 schrieb:
Nimm einfach:
void writeString(std::fstream &file, std::string &str) { file << str.length() << ' '; //write length and seperator file << str; //write string } std::string readString(std::fstream &file) { int len; file >> len; // Read length file.ignore(); //skip ' ' std::string data; data.resize(len); //reserve space for string file.read(&data[0], len); //read string return data;
Länge menschenlesbar, String binär. Dummerweise Länge als int.
Deine direkte Antwort darauf:
Kellerautomat schrieb:
int fuer Laengen ist ne Schnapsidee.
Geschichtsverdrehung?
der die Nachteile von beidem vereint.
Erklär mal. Danach frage ich schon seit 5 Seiten. Bisher kam von dir nur "inkonsistent", "mag ich nicht", "braucht keiner", "Hacker ist doof", "du hast einen an der Waffel", usw. Sachgehalt: 0. Aggressives Verhalten: Hoch.
Um mal einen anderen Thread zu zitieren: Du bist gerade dabei, deinen Account zu verbrennen.
-
SeppJ schrieb:
DarkShadow44 schrieb:
Nimm einfach:
void writeString(std::fstream &file, std::string &str) { file << str.length() << ' '; //write length and seperator file << str; //write string } std::string readString(std::fstream &file) { int len; file >> len; // Read length file.ignore(); //skip ' ' std::string data; data.resize(len); //reserve space for string file.read(&data[0], len); //read string return data;
Länge menschenlesbar, String binär. Dummerweise Länge als int.
Deine direkte Antwort darauf:
Kellerautomat schrieb:
int fuer Laengen ist ne Schnapsidee.
Geschichtsverdrehung?
Hm, ich habe das jetzt nochmal genauestens nachgelesen. Scheinbar hatte ich das wirklich falsch in Erinnerung. Wenn das so ist, entschuldige ich mich bei dir hiermit.
SeppJ schrieb:
der die Nachteile von beidem vereint.
Erklär mal. Danach frage ich schon seit 5 Seiten. Bisher kam von dir nur "inkonsistent", "mag ich nicht", "braucht keiner", "Hacker ist doof", "du hast einen an der Waffel", usw. Sachgehalt: 0. Aggressives Verhalten: Hoch.
Der Sinn von formatierter IO ist, dass Menschen es lesen koennen. Eine Moeglichkeit waere daher, den String in Quotes zu stecken, alle nicht druckbaren Zeichen zu escapen und das dann rauszuschreiben. Bei Lesbarkeit failed die Variante also schon mal, weil es da ein Laengen-Prefix gibt, u.U. "irgendwelche komischen Zeichen", usw..
Bleibt noch binaere IO. Vorteile: Schnell, easy zu parsen. Tja, und da failed die Variante wieder. Ein paar Bytes in einen integer direkt einlesen ist wesentlich einfacher und schneller als einen Zahlenstring einzulesen, in einen integer umzuwandeln, dabei auf Ueberlaeufe zu checken usw.
Ich sehe darin also keine Vorteile, nur Nachteile.
-
Zwei Fehler:
-Vorteile formatierter IO ist nicht nur Menschenlesbarkeit. Ein Hauptvorteil ist Portabilität.
-Ich habe keine Ahnung, wieso du hier Zeichen escapen willst beim String. Es geht schon um binäre Speicherung des Strings. Es geht darum wie du die Länge mitbekommst. Da gibt es eben zwei Methoden, eine unportabel (und meinetwegen 3 µs schneller) und eine portabel.
-
SeppJ schrieb:
Zwei Fehler:
-Vorteile formatierter IO ist nicht nur Menschenlesbarkeit. Ein Hauptvorteil ist Portabilität.Warum sollte binäres Schreiben von Integern nicht portabel lösbar sein? Wenn du das als Nachteil anführst musst du als Gegenargument aber auch die bessere Performance akzeptieren.
Arcoth schrieb:
Als ob das vergleichbar wäre.
Und ob.
Nein.
Arcoth schrieb:
Ich brauche einen
std::string
größer als 4 GiB (bitte Binärpräfixe nutzen), deine These ist widerlegt.Höchstens meine These dass du dann ein Designproblem hast. :p
SeppJ schrieb:
Bei Arrays sehe ichs ja noch ein, aber definitiv nicht für std::string.
Und womit speicher ich mein OTP? vector<char>, obwohl's doch eine Zeichenkette ist? Wie speicherst du vector<char> ab? Auf einmal doch mit size_t?
Du braucht ein OPT dass größer als 4GB ist auf einmal im Speicher? Sicher dass du dein Design nicht nochmal überdenken willst?
Im übrigen sind OTPs idR nicht nur Text, hat also bei mir in std::string nichts zu suchen.
std::vector wird mit uint64_t gespeichert.Arcoth schrieb:
Nachteil
uint64_t
: Du merkst ohne weiteres nicht dass die Länge zu groß ist. Das Programm wird irgendeinen Schabernack treiben. Sollen wir jedes mal wenn wir deinenuint64_t
einlesen explizit prüfen ob er nicht in einenstd::string::size_type
passt? Sogar wenn der Stream-Operator es für uns tun könnte?Ja. Den Fehlerzustand überprüfen musst du ja auch. Und zu testen ob die Länge zu groß ist ist ja jetzt auch nicht viel komplizierter, oder?
Arcoth schrieb:
Ein Leser deines Codes wird sich fragen warum zum Teufel du
uint64_t
für die Länge verwendest, denn deine Argumentation wird er nie im Leben nachvollziehen könnenWeil es so schwer zu verstehen ist dass mein Dateiformat explizit so große strings erlaubt? Bei deiner Lösung sieht man nur, dass die Länge plattformabhängig sind. Ob das Program mit größeren Längen zurecht kommt dagegen nicht.
SeppJ schrieb:
Dann können auch z.B. 32Bit Programme die Länge der großen Strings einlesen und dann einen Fehler ausgeben statt Mist zu bauen.
Seit wann können 32-Bit Programme nicht erkennen, ob eine Zahl größer oder kleiner ist als eine andere? Wo ist der Unterschied, wenn man da uint32_t oder size_t als Datentyp benutzt? Die Fehlerbehandlung fehlt bei deinem momentanen Code sowieso, aber sie wäre in beiden Fällen immer noch gleich.
Was ist mit 16-Bit Programmen?Sie können den Fehler erkennen, ja. Aber sie haben die Länge nicht und müssen die Verarbeitung daher abbrechen statt genau sagen zu können was das Problem ist und es eventuell einfach zu ignorieren.
16Bit Programme? Nenn mir einen Grund warum ich das berücksichtigen sollte. Und selbst wenn, 16Bit kann genauso 64Bit Zahlen einlesen.SeppJ schrieb:
Ich zitiere noch einmal die Frage, vor der du dich die ganze Zeit drückst:
Alle Probleme wären mit einem Schlag gelöst, wenn size_t statt einem anderen Typen genommen würde. Eine einzige Änderung an einer einzigen Stelle, der sonstige Code wäre identisch. Wieso diese Gegenwehr?
Nenne einen Grund, nicht immer size_t zu nehmen. Einen einzigen! Du hast 0 Nachteile durch size_t, der Code ist identisch! Bei allen anderen Typen hast du eine künstliche Unportabilität und/oder Grenze eingebaut. "inkonsistent", "mag ich nicht", "niemand braucht das", sind alles nur Strohmannargumente. Wo ist der sachliche Grund, nicht size_t zu nutzen?
Konsistenz.
Sies doch mal von der anderen Seite: Du hast ein Dateiformat in dem Zahlen vorkommen deren Bitbreite unbekannt ist. Wenn du diese Zahlen mit plattformabhängiger Größe einliest, dann kannst du nicht sicherstellen dass sie eingelesen werden können. Du kannst höchstens sagen dass das Einlesen fehlgeschlagen ist. Während ich mit meinem Ansatz die Länge noch einlesen kann, und die Verarbeitung danach weiterführen, wenn ich das will. Das geht bei dir ja wohl nicht.
-
Ja. Den Fehlerzustand überprüfen musst du ja auch.
Ja, und zwar in beiden Fällen (ich hoffe, du überprüfst den Fehlerzustand des Streams bevor du mit der Länge zu arbeiten anfängst?). Bei deinem Scheiß muss ich zusätzlich die Länge überprüfen bevor ich zu einem
size_t
konvertiere, und das ist redundant und nervig.Weil es so schwer zu verstehen ist dass mein Dateiformat explizit so große strings erlaubt?
Es erlaubt gar nichts.
size_t
(std::allocator<>::size_type
) auf der Leseplatform muss 8 Byte groß sein, sonst kannste einen solchen String nicht in einem Stück extrahieren und speichern, weder mitstring
noch mitnew[]
.Konsistenz.
Seit wann kompensiert deine heißgeliebte "Konsistenz" den anderen Ballast!?
Es ist konsistent, die Länge auch binär zu serialisieren? Sollen vielleicht Gürtel aus demselben Stoff wie Hosen gemacht werden, weil das konsistent zu den Hosen ist? inb4 not comparableWarum sollte binäres Schreiben von Integern nicht portabel lösbar sein?
Es ist portabel lösbar, wenn man die Endianness berücksichtigt. Vorteile? Keine signifikanten.
Aber sie haben die Länge nicht und müssen die Verarbeitung daher abbrechen statt genau sagen zu können was das Problem ist
Falsch.
size_t
wird aufstd::numeric_limits<size_t>::max()
gesetzt wenn die Länge zu groß ist. Die genaue Länge brauchen wir eh nicht, das Programm wird nicht weiter arbeiten können wenn die Daten nicht vollständig eingelesen werden können. Hätten wir Strings nutzen wollen/sollen die kleiner als 4GiB groß sind hätten wir sie auch so serialisiert.und die Verarbeitung danach weiterführen, wenn ich das will.
Was du natürlich niemals tun würdest, diese Möglichkeit existiert nur um sie hier als zusätzliche Option erwähnen zu können. Und falls wir das wollen würden, also den String separat in mehrere einzulesen falls die Länge zu groß ist, könnten wir immer noch im Stream zurückgehen und die Länge in einen
uint64_t
einlesen. Den entsprechenden Code leiten wir mit__builtin_unreachable
ein., dann kannst du nicht sicherstellen dass sie eingelesen werden können
Nein, aber wie wir bereits mehrfach erklärt habe... ach, lassen wirs.
Wenn du das als Nachteil anführst musst du als Gegenargument aber auch die bessere Performance akzeptieren.
Das hier ist kein Spiel nach Punkten. Die zwei Millisekunden die wir "langsamer sind" um dafür sauberen, lesbaren und portablen Code zu haben gönnen wir uns.
-
SeppJ schrieb:
Zwei Fehler:
-Vorteile formatierter IO ist nicht nur Menschenlesbarkeit. Ein Hauptvorteil ist Portabilität.Wie schon gesagt, ich sehe absolut nicht, wo man hier weniger Portabilitaet mit binaerer IO hat. Man muss sich bei beidem auf ein Format einigen. Bei formatierter IO gibt es Dinge wie Encoding, bei binaerer IO eben die Groesse der Typen. Endianess ist kein Problem, man kann Integer Endianess-unabhaengig lesen und schreiben ohne irgendwelche ifs.
SeppJ schrieb:
-Ich habe keine Ahnung, wieso du hier Zeichen escapen willst beim String. Es geht schon um binäre Speicherung des Strings. Es geht darum wie du die Länge mitbekommst. Da gibt es eben zwei Methoden, eine unportabel (und meinetwegen 3 µs schneller) und eine portabel.
Warum willst du ein lesbares File, aber einen binaeren String? Wenn da in dem File steht
14|k3?9 ??} ke?9?
dann ist das absolut nicht lesbar. (Ersetze '?' durch ein nicht druckbares Zeichen deiner Wahl)
Hat man hingegen"k3\x009\n\x01\x02}\nke\x039\x04"
dann ist das sehr schoen lesbar. Und mit Editieren fange ich garnicht erst an.