C Tutorial - Smileys mit fread()

Schnelle objektorientierte, kompilierende Programmiersprache.
CptSparky
Beiträge: 4
Registriert: Fr Aug 29, 2014 4:47 pm

C Tutorial - Smileys mit fread()

Beitrag von CptSparky » Fr Aug 29, 2014 4:55 pm

Hallo, im C-Tutorial "Eine Datei in den Speicher kopieren" bekomme ich bei der verkürzten Version, die nicht den ganzen Speicher der Datei alloziiert, Smileys in 2er Blöcken in die Konsole.
Ich habe das Programm mittels MinGW mit gcc auf nem Win 8 Rechner compiliert.
Konnte es bisher noch nicht auf nem echtem Linux probieren.
Das passiert sowohl in dem MinGW Terminal, das ich benutze, als auch in der DOS Box und der PowerShell Konsole.

Sieht ungefähr so aus:

ha☻ll☻o ☻pr☻og☻ge☻n.☻or☻g


Habe auch versucht, den Quelltext so wie er ist raus zu kopieren, um Fehler zu verhindern. Kommt aber das gleiche.
Hat das Problem noch jemand und was passiert da eigentlich genau?

Danke.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: C Tutorial - Smileys mit fread()

Beitrag von cloidnerux » Fr Aug 29, 2014 5:49 pm

Hi und Willkommen im Forum :D

Bitte mal deinen Source-Code her angeben, damit man das testen kann.
Ansonsten bleibt und nur raten übrig.
Redundanz macht wiederholen unnötig.
quod erat expectandum

CptSparky
Beiträge: 4
Registriert: Fr Aug 29, 2014 4:47 pm

Re: C Tutorial - Smileys mit fread()

Beitrag von CptSparky » Fr Aug 29, 2014 8:14 pm

Hallo,
sorry, ich dachte, meine Beschreibung sei eindeutig.
Weiß jetzt nicht, wie ich es anders formulieren soll.
Ich habe den Sourcecode aus dem Abschnitt "Eine Datei in den Speicher kopieren" des C-Tutorials genommen, ihn in eine Datei file05.c kopiert, im MinGW Terminal "gcc -o file05 file05.c" eingegeben, die exe ausgeführt und das kam raus.

Hier nochmal der Quellcode:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
 
int main (void)
{
  FILE *file = fopen("datei.txt", "a+");
 
  if( file )
  {
    long int read;
    char buffer[2];
 
    while(( read = fread( buffer, sizeof( char ), 2, file ) ))
      printf( "%*s", read, buffer );
 
    printf( "\n" );
 
    fclose(file);
  }
  else
    printf( "Datei konnte nicht geöffnet werden.\n" );
 
  return EXIT_SUCCESS;
}

Was jetzt noch komischer ist:
ich habe die exe - Datei in Dropbox kopiert, um sie zu Hause auf meinem Rechner unter Win 7 zu testen. Jetzt schlägt Avira Alarm, ich hätte da einen "HEUR/APC (Cloud)" Virus drin.

Der Win 8 Rechner auf der Arbeit ist relativ frisch installiert und ein Arbeitsrechner mit Antivirenprogramm. Das Programm habe ich selbst kompiliert.
Hat mir Dropbox da jetzt nen Virus untergejubelt?

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: C Tutorial - Smileys mit fread()

Beitrag von cloidnerux » Fr Aug 29, 2014 9:02 pm

ich habe die exe - Datei in Dropbox kopiert, um sie zu Hause auf meinem Rechner unter Win 7 zu testen. Jetzt schlägt Avira Alarm, ich hätte da einen "HEUR/APC (Cloud)" Virus drin.
Avira dazu:
http://www.avira.com/de/support-threats ... 5/tlang/de
Deine Programme, vor allem wenn sie Pointer inkorrekt (aus)nutzen, können als Virus erkannt werden, aufgrund ihres Verhaltens.
Zur not aber einfach nochmal lokal compilieren.


Dein Sourcecode sieht korrekt aus.

Was nicht korrekt funktioniert ist:

Code: Alles auswählen

printf("%*s", read, buffer);
Der Formatstring "%*s" soll bedeuten, dass ein String ausgegeben wird, dessen Länge in dem Argument vor dem String angegeben ist(read). Unter Windows wird es schlichtweg ignoriert und es wird so lange string ausgegeben, bis ein Null-Byte(0, '\0') kommt, daher kommen die Lustigen Smilies alle 3 Zeichen und die Warnung deines Virenwächters, weil dein Programm über die Grenzen eines Arrays hinaus liest.

Der Workaround:

Code: Alles auswählen

if( file )
{
    long int read;
    char buffer[3];      //1 Byte mehr für das Null-Byte reservieren
    buffer[2] = '\0';      //Null-Byte auch wirklich auf 0 setzten

    while(( read = fread( buffer, sizeof( char ), 2, file ) ))    //Datei lesen
    {
        printf( "%s", buffer );    //Ausgeben
        memset(buffer, 0, 3);   //Buffer wieder komplett auf 0 setzten, damit keine Artefakte entstehen
    }

    printf( "\n" );

    fclose(file);
}
Edit: Das ist falsch:
Ich habe aber gerade die Vermutung, dass deine Textdatei falsch sein könnte.
Dein Terminal Akzeptiert 8-Bit ASCII(UTF-8) Zeichen.
Wenn dein Texteditor aber mehr kann und dein Text als UTF-16 oder ähnlich gespeichert hat, dann ist es erklärlich warum dein Text nicht richtig gelesen wird.
Mit welchem Programm hast du die Textdatei erstellt, welches Zeichenformat wurde benutzt?


Edit 2: @Xin
Gibt es hier egt kein durchgestrichen?
Redundanz macht wiederholen unnötig.
quod erat expectandum

CptSparky
Beiträge: 4
Registriert: Fr Aug 29, 2014 4:47 pm

Re: C Tutorial - Smileys mit fread()

Beitrag von CptSparky » Fr Aug 29, 2014 9:49 pm

Hallo cloidnerux,
vielen Dank für die Infos.
Also mit der Aussage "mein Quellcode" kann ich nicht wirklich leben, denn der Quellcode stammt ja von dem Tutorial Schreiber ;) Was mir aber bis auf ein paar Ausnahmen sehr gut gefällt.

Deine Erklärung klingt ziemlich gut. Denke mittlerweile auch, dass es an meiner Textdatei liegen muss.
Hab die bestehende exe jetzt noch mal unter WINE probiert, hier kommen auch komische Zeichen.
Dann hab ich das Ganze nochmal raus kopiert und unter meinem Linux compiliert, da kommen Klammeraffen.

Meine Textdatei hab ich wie viele der Quellcodes auch unter besagtem Win 8 mit einem frisch installiertem und upgedatetem Notepadd++ erstellt, ohne an den Einstellungen etwas zu ändern.
Muss ich am Montag mal nachsehen, was da Standardmäßig für ein Format eingestellt ist.

Jedenfalls hab ich sowohl unter dem MinGW auf der Arbeit als auch hier unter Linux die Datei mittels cat anzeigen lassen und da kommt der Text ganz normal.

Aber zufrieden bin ich noch nicht. Ich habe jetzt mal mit Kate eine neue Textdatei erzeugt, das heraus kopierte Programm neu compiliert und siehe da, auch mit der unter Linux erzeugten Datei kommen Klammeraffen in die Ausgabe.
(Und nebenbei bemerkt auch eine Warnung bezüglich zweier long ints wo nur ints sein dürften.)

Auffällig ist halt, dass die Zeichen alle 2 Bytes kommen und unser Buffer halt nur 2 char groß ist. Oder sollte das der Anschauungseffekt des Programms sein?

Edit:
Ok, danke. Das muss ich mir nochmal durch den Kopf gehen lassen :?

Allerdings kommt die Ausgabe auch unter Linux (Ubuntu 14.04, 64bit) und somit ist das kein Windows Fehler (Zumal es da ja auch mit gcc compiliert worden ist). Vielleicht könntest du diesen Teil im Tutorial nochmal ausführlicher erklären? Kann mir nicht vorstellen, dass ich da der Einzige sein soll, der da komische Zeichen hat.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Tutorial - Smileys mit fread()

Beitrag von Xin » Fr Aug 29, 2014 10:18 pm

Ich glaube Avira liegt hier nicht ganz verkehrt.... der Quelltext ist falsch. Ich habe ihn im Tutorial bereits geändert.

Bitte ändere folgendes:

Code: Alles auswählen

  FILE *file = fopen("datei.txt", "a+");

zu 

  FILE *file = fopen("datei.txt", "r");
und bitte gib mal Deine Datei 'datei.txt' unter Linux auf die Konsole aus:

Code: Alles auswählen

xin@prgn:~$ hd datei.txt 
00000000  48 61 6c 6c 6f 20 70 72  6f 67 67 65 6e 2e 6f 72  |Hallo proggen.or|
00000010  67 0a                                             |g.|
00000012
Wenn das bei Dir anders aussieht, bitte sagen :-)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: C Tutorial - Smileys mit fread()

Beitrag von cloidnerux » Fr Aug 29, 2014 10:40 pm

Bitte ändere folgendes:

Code: Alles auswählen

  FILE *file = fopen("datei.txt", "a+");
zu

Code: Alles auswählen

  FILE *file = fopen("datei.txt", "r");
Das hat bei mir nicht geholfen, da printf die Längenangabe des Strings einfach ignoriert.
Die selbe Ausgabe mit den Smilies kommt auch bei folgendem Code:

Code: Alles auswählen

while(( read = fread( buffer, sizeof( char ), 2, file ) ))
      printf( "%*s", 0, buffer );
Win 7 74-Bit, GCC 4.8.1
Edit:
Ok, danke. Das muss ich mir nochmal durch den Kopf gehen lassen :?

Allerdings kommt die Ausgabe auch unter Linux (Ubuntu 14.04, 64bit) und somit ist das kein Windows Fehler (Zumal es da ja auch mit gcc compiliert worden ist). Vielleicht könntest du diesen Teil im Tutorial nochmal ausführlicher erklären? Kann mir nicht vorstellen, dass ich da der Einzige sein soll, der da komische Zeichen hat.
Es liegt am printf, siehe mein Edit:
cloidnerux hat geschrieben:Was nicht korrekt funktioniert ist:

Code: Alles auswählen

printf("%*s", read, buffer);
Der Formatstring "%*s" soll bedeuten, dass ein String ausgegeben wird, dessen Länge in dem Argument vor dem String angegeben ist(read). Unter Windows wird es schlichtweg ignoriert und es wird so lange string ausgegeben, bis ein Null-Byte(0, '\0') kommt, daher kommen die Lustigen Smilies alle 3 Zeichen und die Warnung deines Virenwächters, weil dein Programm über die Grenzen eines Arrays hinaus liest.

Der Workaround:

Code: Alles auswählen

if( file )
{
    long int read;
    char buffer[3];      //1 Byte mehr für das Null-Byte reservieren
    buffer[2] = '\0';      //Null-Byte auch wirklich auf 0 setzten

    while(( read = fread( buffer, sizeof( char ), 2, file ) ))    //Datei lesen
    {
        printf( "%s", buffer );    //Ausgeben
        memset(buffer, 0, 3);   //Buffer wieder komplett auf 0 setzten, damit keine Artefakte entstehen
    }

    printf( "\n" );

    fclose(file);
}
Und nochmal die Frage an Xin, kann man im Forum was durchstreichen?
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C Tutorial - Smileys mit fread()

Beitrag von Xin » Fr Aug 29, 2014 11:20 pm

cloidnerux hat geschrieben:Das hat bei mir nicht geholfen, da printf die Längenangabe des Strings einfach ignoriert.
Die selbe Ausgabe mit den Smilies kommt auch bei folgendem Code:

Code: Alles auswählen

while(( read = fread( buffer, sizeof( char ), 2, file ) ))
      printf( "%*s", 0, buffer );
Win 7 74-Bit, GCC 4.8.1
Ich habe das unter Linux ausprobiert und das Programm mit "a+" ergibt keinen Sinn und funktioniert auch nicht.

Ich kann mir nicht vorstellen, dass Windows da einen anderen "Standard" hat - ausprobiert habe ich es jetzt aber noch nicht...
cloidnerux hat geschrieben:Und nochmal die Frage an Xin, kann man im Forum was durchstreichen?
Bisher nicht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: C Tutorial - Smileys mit fread()

Beitrag von cloidnerux » Fr Aug 29, 2014 11:38 pm

Ich habe das unter Linux ausprobiert und das Programm mit "a+" ergibt keinen Sinn und funktioniert auch nicht.
Bei mir macht es keinen unterschied ob "a+" oder "r".
Ich hab es gerade auch mal unter Fedora getestet mit GCC 4.8.3, da macht es auch keinen unterschied ob "a+" oder "r", das Ergebnis ist das selbe.
Ich kann mir nicht vorstellen, dass Windows da einen anderen "Standard" hat - ausprobiert habe ich es jetzt aber noch nicht...
Es scheint, als ob es das Sternchen für die längen angabe so nicht gibt.
Auch nochmal unter Fedora getestet mit

Code: Alles auswählen

printf("%*s", 0, buffer);
ohne Veränderung.
Wenn ich aber wieder buffer auf 3 Elemente erhöhe und das dritte Element auf 0 setzte, funktioniert es, bis auf das Artefakt bei ungerader anzahl Zeichen.
Bisher nicht.
Wollen wir das mal einführen?
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: C Tutorial - Smileys mit fread()

Beitrag von cloidnerux » Fr Aug 29, 2014 11:42 pm

Und hier die Lösung des ganzen: Der Format string ist Falsch.
Im Tutorial heißt es:

Code: Alles auswählen

while(( read = fread( buffer, sizeof( char ), 2, file ) ))
      printf( "%*s", read, buffer );
Es muss aber heißen:

Code: Alles auswählen

while(( read = fread( buffer, sizeof( char ), 2, file ) ))
      printf( "%.*s", read, buffer );
Es fehlt der Punkt vor dem Sternchen um die Längenangabe zu aktivieren, getestet unter Win 7 und Fedora 20.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten