Das String-Nullbyte mit in Datendatei schreiben.
-
Ich will Strings in eine eine binäre Datei, die mit fopen geöfnet wurde, schreiben. Und zwar mit dem Nullbyte am Ende.
Mein Versuch
fprintf(fpointer,"%s\0",string);
funktioniert nicht. Ich erhalte in der Datei nur den String an sich, aber nicht die \0 am Ende.
Wie mache ich das?
-
du verwendest fprintf. Die printf-Funktionen erwarten \0-abgeschlossene Zeichenketten. Für printf sind deshalb "abc" und "abc\0" die selben Strings, da nach 'c' \0 kommt. Was danach kommt, weiß printf nicht (und will es auch nicht wissen).
Vielleicht akzeptiert man: fputc(3) \0 als Eingabe und schreibt es auch, hab's nie ausprobiert. Ansonsten musst du auf eine OS-abhängige Funktion zugreifen, mit der du beliebige Bytes schreiben kannst, wie z.b. write
-
Interessantes Problem. So geht das jedenfalls nicht, weil ein String-Literal eine implizite Null am Ende hat. Wenn du eine zweite dazu machst, hört printf() eben bei dieser auf.
Am einfachsten ist wahrscheinlich, ein
putc(0, fpointer)
anzuhängen.
-
Das habe ich jetzt so gemacht. Und es funktioniert. Danke
Ist die Null denn bei Dateien unüblich?
-
So könnte es auch gehen:
fprintf(fpointer, "%s%c", string, 0);
-
Franky666 schrieb:
Ist die Null denn bei Dateien unüblich?
Nein, gar nicht. Es ist nur so, dass die in C das Ende eines Strings markiert.
-
Franky666 schrieb:
Das habe ich jetzt so gemacht. Und es funktioniert. Danke
Ist die Null denn bei Dateien unüblich?bei plain-text Dateien ja, weil \0 nicht darstellbar ist bzw. keine Darstellung hat. Bei binären Dateien ist es jedoch üblich, aber da verwendet man keine printf-Funktionen, um zu schreiben.
-
was nimmt man dann?
-
Franky666.1 schrieb:
was nimmt man dann?
Wenn die Nullbytes stören, kannst du putc() oder fwrite() oder sowas nehmen. Aber wenn's mit fprintf() einfacher geht, dann mach's eben so.
-
die nullbytes stören ja nicht, der gegenteil war der Fall, sie fehlten
ich habe hier eine auf das relevante reduzierte Befehlszeile als Musterbeispiel meines Vorhabens dargestellt. In Wirklichkeit des Programms schreibt der besagte fprintf statt dem einen string eine ganze Dynamische Liste mit Ziffern und Zeichen in formatierter Form in eine Datei. Damit der Lesevorgang die Strings korrekt liest, müssen die 0'en auch mit rein. Ich finde, das ist dann mit fprintf einfacher :p. Wo llte hier nur nicht einen halben km Befehl mit Deklarations-Programmstückchen hinschreibenAber es ist nicht grundsätzlich ein grober Fehler, in diesem Fall mit fprintf da rein zu gehen, oder?
-
Franky666.1 schrieb:
Aber es ist nicht grundsätzlich ein grober Fehler, in diesem Fall mit fprintf da rein zu gehen, oder?
Wenn's läuft, kann's nie ein grober Fehler sein.
Franky666.1 schrieb:
Damit der Lesevorgang die Strings korrekt liest, müssen die 0'en auch mit rein.
Wie kommt das?
-
Franky666.1 schrieb:
Damit der Lesevorgang die Strings korrekt liest, müssen die 0'en auch mit rein.
nein, das ist falsch. In einer Textdatei müssen keine \0 Zeichen rein, weil das Dateisystem das Dateiende kennt. Es sind Funktionen wie
fgets
, die die zusätzlichen \0-Zeichen beim Lesen im Lesepuffer reintun, um konforme C-Strings zurückzugeben.Ich würde sogar sagen, dass das sogar gefährlich ist. Da ich die Implementierung von fgets nicht kenne, weiß ich nichts, ob folgende Vermutung wahr ist: es könnte sowas passieren. Stell dir vor, du machst:
fprintf(output, "a b c%cd e f\ng h i\n", 0);
dann gibt es in der Datei
a b c\0d e f\ng h i\n<EOF>
wenn fgets sich nur an der Puffergröße und \n verlässt und du machst
char line[1024]; fgets(line, sizeof line, input); printf("'%s'\n", line); fgets(line, sizeof line, input); printf("'%s'\n", line);
dann würde ich sagen, dass der Output so aussehen wird
'a b c' 'g h i'
wenn fgets schlau ist, dann sollte das nicht passieren.
-
Franky666.1 schrieb:
Aber es ist nicht grundsätzlich ein grober Fehler, in diesem Fall mit fprintf da rein zu gehen, oder?
Die Frage ist, ob Du nur Strings reinstopfen oder die Formatstringoptionen nutzen magst. fprintf ist wie alle seine Brüder und Schwestern ein wenig gehbehindert, fwrite schon flotter unterwegs. Die Null kriegst Du am undramatischsten mit fputc(0, outfile) hin.
Ich nehm' halt fprintf nur her, wenn ich's wirklich brauch'.
-
supertux schrieb:
dann würde ich sagen, dass der Output so aussehen wird
'a b c' 'g h i'
wenn fgets schlau ist, dann sollte das nicht passieren.
fgets und schlau? Wer träumt? Genau das dürfte passieren. fgets liest die '\0' einfach mit, weil es sich nur um '\n' oder EOF kümmert, für printf() endet die auszugebende Welt bei genau dieser Null.
Überhaupt sind zeichenterminierte streams nicht wirklich intelligent, aber bevor man draufgekommen ist, war die <string.c> schon fertig und irgendein Trottel hatte schon damit angefangen, UNIX zu bauen.
Tja, so blöd kann's gehen
-
Ich muss den Thread nochmal hochkellern. Und zwar muss ich diese Strings wieder auslesen. Wie mache ich das? fgets funkitioniert nicht und ließt ja bis zu einem Zeilenumbruch und fscanf scheidet durch Leerzeichen aus. Aber mit was lese ich nullterminierte Strings aus der Datei?
-
Franky666.1 schrieb:
Ich muss den Thread nochmal hochkellern. Und zwar muss ich diese Strings wieder auslesen. Wie mache ich das? fgets funkitioniert nicht und ließt ja bis zu einem Zeilenumbruch und fscanf scheidet durch Leerzeichen aus. Aber mit was lese ich nullterminierte Strings aus der Datei?
Wie wärs mit fgetc?
-
Franky666.1 schrieb:
Ich muss den Thread nochmal hochkellern. Und zwar muss ich diese Strings wieder auslesen. Wie mache ich das? fgets funkitioniert nicht und ließt ja bis zu einem Zeilenumbruch und fscanf scheidet durch Leerzeichen aus. Aber mit was lese ich nullterminierte Strings aus der Datei?
Wenn du weisst, wie lang sie sind, am besten mit fread(). Im schlimmsten Fall kann man auch selbst was bauen:
#include <stdio.h> /* Bis zur nächsten Null oder bis EOF lesen, die Null mitlesen. Höchstens 'max' Zeichen lesen. Die Anzahl der gelesenen Zeichen (ohne die Null) zurückgeben. */ size_t read_until_null(char *buf, size_t max, FILE *stream) { int c; char *start = buf; max--; while ((c = getc(stream)) && c != EOF && max--) *buf++ = c; *buf = 0; return buf - start; } int main(void) { FILE *in = fopen("in.txt", "r"); char text[64]; size_t count; count = read_until_null(text, sizeof text, in); puts(text); fclose(in); return 0; }
Oder so ähnlich.
-
mngbd schrieb:
Oder so ähnlich.
Die Betonung liegt auf ähnlich
( dies ist ein Arrayexplosionbeispiel :p ) und der Parmeter sizeof (text) -1 tut der Ähnlicheit keinen Abbruch.
-
Big Brother schrieb:
Die Betonung liegt auf ähnlich
( dies ist ein Arrayexplosionbeispiel :p ) und der Parmeter sizeof (text) -1 tut der Ähnlicheit keinen Abbruch.
Stimmt. Ausserdem kann man nicht unterscheiden, ob man EOF oder mehrere Nullen hintereinander gefunden hat. Ein schlauer Mensch würde das wohl anders machen.
-
@Franky666.1
du schreibst immer du willst das und jenes machen. Erst kommst du damit die Strings mit der '\0' am Schluss mit in die Datei zu schreiben, dann weisst du nicht wie man das Ganze ausliest.
Möglicherweis wäre es sinnvoller dein Vorhaben (also das was das fertige Programm eigentlich machen soll) zu schildern und nachzufragen wie man das am besten lösen kann. Der Vollständigkeit halber kannst du ja deinen Denkansatz mit einbringen.