Warum zeigt mein einfaches C-Programm Müll an?

8

Betrachten Sie das folgende einfache C-Programm, das eine Datei in einen Puffer liest und diesen Puffer der Konsole anzeigt:

%Vor%

Die zu lesende Datei enthält einfach:

  

Hallo Welt!

Die Ausgabe ist:

  

Hallo Welt! ²²²²▌▌▌▌▌▌▌↔☺

Es ist eine Weile her, seit ich etwas Bedeutendes in C / C ++ gemacht habe, aber normalerweise würde ich annehmen, dass der Puffer größer als nötig zugewiesen wurde, aber das scheint nicht der Fall zu sein.

fileLen endet mit 12, was genau ist.

Ich denke jetzt, dass ich nur den Puffer falsch anzeigen muss, aber ich bin mir nicht sicher, was ich falsch mache.

Kann mir jemand sagen, was ich falsch mache?

    
GEOCHET 03.11.2008, 22:43
quelle

5 Antworten

38

Sie müssen die Zeichenfolge NULL-terminieren. Fügen Sie

hinzu %Vor%

vor dem Drucken.

    
JesperE 03.11.2008, 22:45
quelle
28

Der Ansatz von JesperE wird funktionieren, aber Sie könnten daran interessiert sein, dass es einen alternativen Weg gibt, um damit umzugehen.

Sie können immer eine Zeichenfolge mit bekannter Länge drucken, selbst wenn kein NUL-Terminator vorhanden ist, indem Sie die Länge auf printf als Genauigkeit für das Zeichenfolgenfeld angeben:

%Vor%

Dadurch können Sie die Zeichenfolge drucken, ohne den Puffer zu ändern.

    
George Eadon 03.11.2008 23:14
quelle
8

JesperE ist in Bezug auf das Null-Abbruch-Problem in Ihrem Beispiel korrekt, ich füge nur hinzu, dass wenn Sie Textdateien verarbeiten, es besser wäre, fgets () oder etwas Ähnliches zu verwenden, da dies Zeilenumbrüche auf verschiedenen Plattformen korrekt behandelt und wird immer die Zeichenfolge für Sie beenden. Wenn Sie wirklich mit binären Daten arbeiten, dann möchten Sie printf () nicht verwenden, um die Daten auszugeben, da die printf-Funktionen Zeichenfolgen erwarten, und ein Null-Byte in den Daten bewirkt eine Kürzung der Ausgabe.

    
Robert Gamble 03.11.2008 23:13
quelle
2

Ihr Ansatz, die Dateigröße zu bestimmen, indem Sie bis zum Ende der Datei suchen und dann ftell() verwenden, ist falsch:

  • Wenn es sich um eine Textdatei handelt, die ohne "b" im zweiten Parameter für den Aufruf fopen() geöffnet wurde, kann ftell() Ihnen möglicherweise nicht die Anzahl der Zeichen mitteilen, die Sie aus der Datei lesen können. Zum Beispiel verwendet Windows zwei Bytes für das Ende der Zeile, aber beim Lesen ist es ein char . Tatsächlich ist der Rückgabewert von ftell() für im Textmodus geöffnete Streams nur in Aufrufen von fseek() nützlich, und nicht zum Ermitteln der Dateigröße.
  • Wenn es sich um eine Binärdatei handelt, die mit "b" im zweiten Parameter zu fopen() geöffnet wurde, dann sagt der C-Standard:
      

    Das Festlegen des Dateipositionsindikators auf das Dateiende, wie bei fseek(file, 0, SEEK_END) , hat ein undefiniertes Verhalten für einen binären Datenstrom (wegen möglicher abschließender Nullzeichen) oder für jeden Datenstrom mit zustandsabhängiger Codierung, der nicht sicher endet im anfänglichen Schaltzustand.

Also, was Sie tun, wird nicht unbedingt in Standard C funktionieren. Am besten verwenden Sie fread() zum Lesen, und wenn Sie mehr Speicher benötigen, verwenden Sie realloc() . Ihr System stellt möglicherweise mmap() zur Verfügung oder kann Garantien geben, den Dateipositionsindikator auf das Dateiende für binäre Datenströme zu setzen - aber darauf angewiesen, dass diese nicht portierbar sind.

Siehe auch diese C-FAQ: Worin besteht der Unterschied zwischen Text und binären E / A? . p>     

Alok Singhal 16.01.2010 03:06
quelle
0

Sie können calloc anstelle von malloc verwenden, um bereits initialisierten Speicher zuzuweisen. calloc übernimmt zusätzliches Argument. Es ist nützlich für die Zuordnung von Arrays; Der erste Parameter von calloc gibt die Anzahl der Elemente im Array an, denen Sie Speicher zuweisen möchten, und das zweite Argument ist die Größe jedes Elements. Da die Größe von char immer 1 ist, können wir einfach 1 als zweites Argument übergeben:

%Vor%

In C muss der Rückgabewert von malloc oder calloc nicht umgesetzt werden. Das Obige stellt sicher, dass die Zeichenfolge null beendet wird, selbst wenn das Lesen der Datei aus irgendeinem Grund vorzeitig beendet wird. calloc dauert länger als malloc , weil es den gesamten Speicher, den Sie angefordert haben, auf Null setzen muss, bevor Sie es Ihnen geben.

    
dreamlax 16.01.2010 02:56
quelle

Tags und Links