www.mikrocontroller.net

Forum: Compiler & IDEs Programm mit getc()


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
für ein Programm brauche ich die base64-Codierung. Ich habe mir mal das 
in der Wikipedia verlinkte Beispielprogramm 
http://base64.sourceforge.net/b64.c angesehen.

Dort gibt es folgenden Code (Ausschnitt):
while( !feof( infile ) ) {
    len = 0;
    for( i = 0; i < 3; i++ ) {
        in[i] = (unsigned char) getc( infile );
        if( !feof( infile ) ) {
            len++;
        }
        else {
            in[i] = 0;
        }
     }
.
.
Da die Abfrage auf EOF nur oben in der while-Bedingung stattfindet, kann 
getc() ja über EOF hinaus einlesen. Gibt es dann nicht einen Fehler?
Ist der Wert von EOF festgelegt, er fließt ja eigentlich laut diesem 
Beispiel mit in den codierten String ein.

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Quelltext ist in der Tat unschön.
      if( !feof( infile ) ) {
            len++;
        }
        else {
            in[i] = 0;
        }

Hier wird bei EOF eine 0 abgespeichert.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Laut manpage liefert getc() das nächste Zeichen, also wird der 
Filepointer erhöht.
Wird aber nun generell in getc() abgefragt ob der FP schon am Ende ist?

In stdio.h sieht es so aus
__CRT_INLINE int __cdecl getc (FILE* __F)
{
  return (--__F->_cnt >= 0)
    ?  (int) (unsigned char) *__F->_ptr++
    : _filbuf (__F);
}

Wenn ich noch wüsste, woher __F->_cnt stammt wär ich schlauer...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas wrote:
> Hi,
> Dort gibt es folgenden Code (Ausschnitt):
>
> while( !feof( infile ) ) {
>     len = 0;
>     for( i = 0; i < 3; i++ ) {
>         in[i] = (unsigned char) getc( infile );
>         if( !feof( infile ) ) {
>             len++;
>         }
>         else {
>             in[i] = 0;
>         }
>      }
> .
> .
> 
> Da die Abfrage auf EOF nur oben in der while-Bedingung stattfindet,

Nicht ganz.
Schau dir mal die Zeile nach dem getc() an.

Aber: In der Tat wird dieses immer wieder, selbst in Lehrbüchern,
falsch gemacht.
Die Funktione feof() ist nicht dazu gedacht, um damit die Schleife
zu steuern. Die korrekte Art und weise geht immer so:

   while( Zeichen konnte gelesen werden ) {
     verarbeite Zeichen;
   }

   if( eof ist nicht aufgetreten )
     Behandle Fehlerbedinung beim Lesen vom File
   else
     File wurde komplett gelesen, mach mit dem gelesenen weiter

C unterstützt dieses Schema dadurch, dass ausnahmslos alle
File Lese Funktionen einen Returnwert haben, der sich zur
Abfrage 'Zeichen konnte gelesen werden' eignet.

Im Falle von getc() liefert getc das Zeichen, bzw. EOF wenn
etwas schief gelaufen ist.

D.h. man zieht diese Schleife korrekter Weise so auf:

  int c;

  i = 0;

  while( ( c = getc( infile ) ) != EOF && i < 3 ) {
    in[i] = (unsigned char)c;
  }

  in[i] =  '\0';

  if( !feof( infile ) ) {
    // Behandle die Fehlerbedingung: einlesen vom File ging schief
  }
  else {
    // Behandle den Fall: die Daten wurden korrekt gelesen
  }

Der Unterschied zwischen der Methode hier und der original
Methode ist ganz einfach der, dass letztere Variante in
jedem Fall abbricht, wenn nicht korrekt vom File gelesen werden
konnte. In der ersten Methode kann es passieren, dass dies
ncith der Fall ist. Nämlich dann, wenn das File nicht bis zum
Ende gelesen wurde aber ein Fehler auftrat (Diskette fehlerhaft,
Kratzer in der CD, jemand hat das Laufwerk aufgemacht, Netzwerk-
verbindung ist abgebrochen, etc. Es gibt viele Gründe warum ein
Lesen von einem File schief gehen kann, nicht nur feof().

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz, du musst i noch erhöhen nach jeder Iteration, ansonsten geht 
die Dauer der Schleife gegen Unendlich ;)

Btw, du (oder irgend jemand anderes) hattest das schonmal geschrieben. 
Ohne diese Information hätte ich es aber auch 100% falsch gemacht (bzw 
sogar falsch gelernt...).

Es wird nämlich tatsächlich in Lehrbüchern falsch gemacht...

Der "Trick" bei der Sache ist, dass getc() höchstens ein Zeichen(char) 
lesen kann, aber einen int zurückgibt. Dadurch ist noch etwas "Platz" um 
Fehler zu kennzeichnen, ohne dass das Zeichen zerstört werden würde.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.