Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?
-
@Belli sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Das brauchst Du nicht zu prüfen: wenn eine Folge von chars im Speicher nicht 0-terminiert ist, ist es kein String.
Umgekehrt: Ein (C-)String ist immer nullterminiert, weil es sonst kein (C-)String ist.Du weisst schon, dass die Realität oft nicht so schön wohldefiniert und widerspruchsfrei wie die mathematische Theorie ist, oder? Dann ist die Aufgabe eben: "Prüfen Sie, ob die char-Folge ein C-String ist".
-
Vielleicht sollten wir warten bis sich @SophiaL wieder meldet und dann hoffentlich die KONKRETE AUFGABE preisgibt.
-
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Vielleicht sollten wir warten bis sich @SophiaL wieder meldet und dann hoffentlich die KONKRETE AUFGABE preisgibt.
Schon klar. ich finde es nur verwunderlich, dass sich hier ein paar so an deiser C-String-Konvention festgebissen haben. Ich finde es völlig klar, dass hier nach einem Programm gefragt ist, das prüft, ob der Speicherbereich einen 0-Char enthält, bevor dieser zuende ist und nicht nach einem mathematischen Beweis mit klaren Definitionen. Wann konnte man sich schonmal bei Software darauf verlassen, dass sie bugfrei ist, und solche Konventionen immer eingehalten werden?
-
@A-Grau sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Aber es ist doch eher ungewöhnlich, das mehrere String-Typen nebeneinander verwendet werden.
Warum?
Es spielt aber auch keine Rolle. Die Bytes hinter einem String sind per se undefiniert. Es könnte ein weiterer String, ein double Wert oder eine Adresse gespeichert sein. Und sobald diese ein Nullbyte enthalten zeigt dein Algo ein Fehler an. Und selbst bei freiem Speicher ist es undefiniert.
Kleiner Tipp: Probiere es mal selbst aus. Lege den Zeiger auf einen int32_t, initialisiere den Int Wert mit 0xAABBCCDD und suche dann dein Nullbyte. Ich wette du stößt relativ schnell auf ein Nullbyte.
-
@SophiaL sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?
so:
bool isNullTerminated(const std::string &s) { return s[s.size()] == '\0'; }
Ausnahmsweise darf man bei std::string im geschlossenen Intervall
[0, size()]
indexieren statt wie sonst üblich im halboffenen Intervall[0, size()[
. Siehe https://en.cppreference.com/w/cpp/string/basic_string/operator_at.
-
@Finnegan Ich wollte eigentlich d'rauf hinaus, daß der bloße Zugriff undefined behaviour hat.
-
Wenn man weiss wie gross der Puffer ist, kann man prüfen ob im Puffer irgendwo ein NUL-Terminator ist. Kann man damit prüfen ob "der String" NUL-terminiert ist? Nicht unbedingt. Ich könnte einen 100 Zeichen Puffer haben und an Position 50 steht ein NUL Zeichen. Weiss ich jetzt dass "der String" NUL-terminiert ist? Nein, denn "der String" den irgendjemand reingeschrieben hat könnte auch nur 4 Zeichen lang und nicht terminiert sein. Ist also irgendwo Definitionssache was "der String" ist.
Oder anders gesagt: man kann nur prüfen ob ein Puffer terminiert ist, und das auch nur wenn man weiss wie gross er ist.
Der einzige Fall wo man prüfen kann ob "der String" NUL-terminiert ist ist, wenn man weiss wie lange "der String" ist, und dass der Puffer mindestens ein Zeichen länger ist.
ps: Und natürlich meine ich Code-Unit wenn ich "Zeichen" schreibe. Ich wollte eventuelle Anfänger die das lesen nur nicht noch mehr verwirren.
-
Was die Frage wie UTF-8 oder UTF-16 String terminiert sind angeht...
Na entweder gar nicht (wenn man mit nicht terminierten Strings arbeitet), oder wie jeder andere normale NUL-terminierte String auch: mit einer NUL Code-Unit. Wobei eine Code-Unit bei UTF-8 ein Byte lang ist, bei UTF-16 zwei Bytes und bei UTF-32 sind es dann 4 Bytes.
Das schöne bei UTF-8 und UTF-16 ist ja dass der Wertebereich der mittleren und hinteren Code-Units eingeschränkt ist und u.A. niemals 0 sein kann. D.h. wenn man eine Code-Unit mit Wert 0 liest, dann weiss man dass man am Ende angekommen ist. Und wenn noch Code-Units fehlen um die aktuelle Sequenz abzuschliessen, dann ist man trotzdem am Ende und hat einfach nur einen unvollständige Sequenz am Ende die man nicht dekodieren kann.
-
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
@Finnegan Ich wollte eigentlich d'rauf hinaus, daß der bloße Zugriff undefined behaviour hat.
Verstehe. Liegt vielleicht daran, dass ich meistens in einer Welt programmiere, wo ich weiss, wie gross ein Speicherbereich ist, auf den ich ohne UB zugreifen darf - wenn mich nicht mal wieder irgendeine Lib zu was anderem zwingt
@hustbaer sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Ich könnte einen 100 Zeichen Puffer haben und an Position 50 steht ein NUL Zeichen. Weiss ich jetzt dass "der String" NUL-terminiert ist? Nein,
Zumindest kann man wissen dass man "einen String" hat, der nullterminiert ist - das ist auch schonmal was, wenn weiterer Code nur komische Werte produziert, statt an UB zu zerschellen
-
@Finnegan Ja, ich hab ja geschrieben "Ist also irgendwo Definitionssache was "der String" ist."
-
@Finnegan sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
@Belli sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Das brauchst Du nicht zu prüfen: wenn eine Folge von chars im Speicher nicht 0-terminiert ist, ist es kein String.
Umgekehrt: Ein (C-)String ist immer nullterminiert, weil es sonst kein (C-)String ist.Du weisst schon, dass die Realität oft nicht so schön wohldefiniert und widerspruchsfrei wie die mathematische Theorie ist, oder? Dann ist die Aufgabe eben: "Prüfen Sie, ob die char-Folge ein C-String ist".
Ja, es kommt halt auf jedes Wort an, so wie SeppJ immer so schön betont, bei einem Programm auf jedes Zeichen.
Ich weiß natürlich was Du meinst, so wie Du auch weißt, was ich meine, trotzdem halte ich es für riskant, die Aufgabenstellung so anzupassen, dass eine gefundene 'Lösung' richtig ist.
Wer sagt denn, dass der Aufgabensteller nicht genau die Antwort haben will, die ich gegeben habe?Deshalb vielleicht:
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Vielleicht sollten wir warten bis sich @SophiaL wieder meldet und dann hoffentlich die KONKRETE AUFGABE preisgibt.
-
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Und ja, ein Zeichen in UTF-16 ist mindestens 16 bit breit.
Mindestens, oder exakt?
Ich dachte bisher, nur bei UTF8 können Zeichen unterschiedliche Bitbreiten haben.
-
@A-Grau sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Und ja, ein Zeichen in UTF-16 ist mindestens 16 bit breit.
Mindestens, oder exakt?
Ich dachte bisher, nur bei UTF8 können Zeichen unterschiedliche Bitbreiten haben.Mindestens. Eine Code-Unit von UTF-16 hat exakt 16 Bit, und ein Code-Point kann aus einer oder Zwei Code-Units bestehen (Stichwort Surrogate-Pairs). Weiters kann aber auch ein "Zeichen" (Glyph) aus mehreren Code-Units bestehen (Stichwort Combining Diacritics).
-
@Ein-ehemaliger-Benutzer sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
@Swordfish sagte in Wie sieht ein Programm aus, das prüft, ob ein String tatsächlich mit einem \0-Zeichen terminiert ist?:
Und ja, ein Zeichen in UTF-16 ist mindestens 16 bit breit.
Mindestens, oder exakt?
Ich dachte bisher, nur bei UTF8 können Zeichen unterschiedliche Bitbreiten haben.Falsch gedacht - und ein häufiges Missverständnis. Mindestens! Das kannst du dir auch leicht überlegen, denn es gibt aktuell ca 250.000 Code Points (siehe https://www.unicode.org/versions/Unicode6.2.0/appD.pdf#page=3), ein 16-Bit-Wert kann aber nur verschiedene Werte darstellen.
Lies mal https://utf8everywhere.org/ - Zitat:
UTF-16 is often misused as a fixed-width encoding, even by the Windows package programs themselves: in plain Windows edit control (until Vista), it takes two backspaces to delete a character which takes 4 bytes in UTF-16. On Windows 7, the console displays such characters as two invalid characters, regardless of the font being used.
Du bist also nicht allein mit dieser Fehlannahme.