Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 18 Ein-/Ausgabe-Funktionen
  gp 18.1 Was ist eine Datei?
  gp 18.2 Formatierte und unformatierte Ein-/Ausgabe
  gp 18.3 Streams
  gp 18.4 Höhere Ein-/Ausgabe-Funktionen
  gp 18.5 Datei (Stream) öffnen – fopen
    gp 18.5.1 Modus für fopen()
    gp 18.5.2 Maximale Anzahl geöffneter Dateien – FOPEN_MAX
  gp 18.6 Zeichenweise Lesen und Schreiben – getchar und putchar
    gp 18.6.1 Ein etwas portableres getch()
  gp 18.7 Zeichenweise Lesen und Schreiben – putc/fputc und getc/fgetc
  gp 18.8 Datei (Stream) schließen – fclose
  gp 18.9 Formatiertes Einlesen/Ausgeben von Streams mit fprintf und fscanf
  gp 18.10 Standard-Streams in C
    gp 18.10.1 Standard-Streams umleiten
  gp 18.11 Fehlerbehandlung von Streams – feof, ferror und clearerr
  gp 18.12 Gelesenes Zeichen in die Eingabe zurück-schieben – ungetc
  gp 18.13 (Tastatur-)Puffer leeren – fflush
    gp 18.13.1 Pufferung
  gp 18.14 Stream positionieren – fseek, rewind und ftell
  gp 18.15 Stream positionieren – fsetpos, fgetpos
  gp 18.16 Zeilenweise Ein-/Ausgabe von Streams
    gp 18.16.1 Zeilenweise Lesen mit gets/fgets
    gp 18.16.2 Zeilenweise Schreiben mit puts/fputs
    gp 18.16.3 Zeilenweise Einlesen vom Stream mit getline() (nicht ANSI C)
    gp 18.16.4 Rezepte für zeilenweises Einlesen und Ausgeben
  gp 18.17 Blockweise Lesen und Schreiben – fread und fwrite
    gp 18.17.1 Blockweises Lesen – fread()
    gp 18.17.2 Blockweises Schreiben – fwrite()
    gp 18.17.3 Big-Endian und Little-Endian
  gp 18.18 Datei (Stream) erneut öffnen – freopen
  gp 18.19 Datei löschen oder umbenennen – remove und rename
    gp 18.19.1 remove()
    gp 18.19.2 rename()
  gp 18.20 Pufferung einstellen – setbuf und setvbuf
  gp 18.21 Temporäre Dateien erzeugen – tmpfile und tmpnam
    gp 18.21.1 mkstemp() – Sichere Alternative für Linux/UNIX (nicht ANSI C)
  gp 18.22 Fehlerausgabe mit strerror und perror
  gp 18.23 Formatiert in einem String schreiben und formatiert aus einem String lesen – sscanf und sprintf
  gp 18.24 Fortgeschrittenes Thema
  gp 18.25 Low-Level-Datei-I/O-Funktionen (nicht ANSI C)
  gp 18.26 Datei öffnen – open
  gp 18.27 Datei schließen – close
  gp 18.28 Datei erzeugen – creat
  gp 18.29 Schreiben und Lesen – write und read
  gp 18.30 File-Deskriptor positionieren – lseek
  gp 18.31 File-Deskriptor von einem Stream – fileno
  gp 18.32 Stream von File-Deskriptor – fdopen


Galileo Computing - Zum Seitenanfang

18.7 Zeichenweise Lesen und Schreiben – putc/fputc und getc/fgetc  toptop

Die Funktionen getc() und fgetc() sind das dateiorientierte Gegenstück zu getchar(). Sie werden verwendet, um einzelne Zeichen aus einem Stream zu lesen, der zuvor mit fopen() geöffnet wurde. Der Unterschied zwischen getc() und fgetc() liegt darin, dass fgetc() als eine Funktion implementiert ist und getc() ein Makro sein darf. Hier die Syntax dazu:

#include <stdio.h>
int getc(FILE *datei);
int fgetc(FILE *datei);

Folgende beiden Schreibweisen sind dabei identisch:

// liest ein Zeichen aus der Standardeingabe
getchar();
// liest ebenfalls ein Zeichen aus der Standardeingabe
fgetc(stdin);

Dazu folgt ein Listing, welches eine Datei zum Lesen öffnet und anschließend den Inhalt der Datei Zeichen für Zeichen auf dem Bildschirm ausgibt. Eingelesen wird so lange, bis das Zeichen für Dateiende oder Fehler erreicht wird (EOF).

/* fgetc1.c */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
   int c;
   FILE *datei;
   datei=fopen("test.txt", "r");
   if(datei != NULL) {
      while( (c=fgetc(datei)) != EOF)
         putchar(c);
   }
   else {
      printf("Konnte Datei nicht finden bzw. öffnen!\n");
      return EXIT_FAILURE;
   }
   return EXIT_SUCCESS;
}

Bei diesem Programm wird zuerst versucht, eine Textdatei im Lesemodus zu öffnen. Falls dies gelungen ist, wird der Text zeichenweise ausgelesen mit

while( (c=fgetc(datei)) != EOF)

und mit putchar() zeichenweise auf dem Bildschirm ausgegeben, bis ein Fehler oder EOF auftritt. Das Programm soll ein wenig erweitert werden:

/* fgetc2.c */
#include <stdio.h>
#include <stdlib.h>
void read_char(FILE *stream) {
   int c;
   while( (c=fgetc(stream)) !=EOF)
      putchar(c);
}
int main(int argc, char **argv) {
   FILE *datei;
   char filename[255];
   /* Falls die Datei zum Öffnen nicht
    * als Argument übergeben wurde ... */
   if(argc < 2) {
      printf("Welche Datei wollen sie öffnen : ");
      scanf("%s",filename);
      datei = fopen(filename ,"r");
      if(datei != NULL)
         read_char(datei);
      else {
         printf("Fehler beim Öffnen von %s\n",filename);
         return EXIT_FAILURE;
      }
   }
   else {
      datei=fopen(argv[1],"r");
      if(datei != NULL)
         read_char(datei);
      else {
         printf("Konnte %s nicht öffnen!\n",argv[1]);
         return EXIT_FAILURE;
      }
   }
   return EXIT_SUCCESS;
}

In diesem Beispiel kann die Datei, die es zu öffnen gilt, über die Kommandozeile eingegeben werden oder erst nach dem Start des Programms. Es empfiehlt sich, diese Schreibweise allgemein für Konsolenprogramme zu verwenden. Damit ist zumindest sichergestellt, dass auch Anwender, die mit dem Programm nicht vertraut sind, es bedienen können.

Als Nächstes das Gegenstück der Funktionen getc() und fgetc(). Für die beiden Funktionen putc() und fputc() gilt hinsichtlich ihres Unterschieds dasselbe wie bei getc() und fgetc(). fputc() ist somit als Funktion implementiert, und putc() darf ein Makro sein. Mit putc()/fputc() kann zeichenweise in einen Stream geschrieben werden. Die Syntax dieser Funktionen lautet:

#include <stdio.h>
int putc(int quellen, FILE *ziel);
int fputc(int quellen, FILE *ziel) ;

Damit wird das Zeichen quelle in den Stream ziel geschrieben. Der Rückgabewert ist das Zeichen in quelle oder bei Fehler bzw. Dateiende EOF.

Dazu ein Listing, mit dem Sie eine Datei zeichenweise kopieren können:

/* copy_char4char.c */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
   FILE *quelle, *ziel;
   int c;
   char name_q[255], name_z[255];
   printf("Name Quelldatei : ");
   scanf("%s",name_q);
   quelle=fopen(name_q,"rb");
   if(quelle == NULL) {
      printf("Konnte %s nicht finden bzw. öffnen!\n",name_q);
      return EXIT_FAILURE;
   }
   else {
      printf("Name Zieldatei : ");
      scanf("%s",name_z);
      ziel=fopen(name_z,"w+b");
      if(ziel==NULL)  {
         printf("Konnte Zieldatei nicht erzeugen!\n");
         return EXIT_FAILURE;
      }
      else {
         /*Wir kopieren zeichenweise von quelle nach ziel */
         while( (c=getc(quelle)) != EOF)
            putc(c,ziel);
      }
   }
   return EXIT_SUCCESS;
}

In diesem Beispiel werden zwei Streams verwendet – einer, mit dem die Datei geöffnet wird, um daraus zu lesen, und ein zweiter, mit dem in eine weitere geöffnete Datei geschrieben wird:

FILE *quelle, *ziel;

Passend werden diese Streams quelle und ziel benannt. Zuerst wird eine Datei zum Lesen im "rb"-Modus geöffnet. Anschließend erfolgt eine Abfrage, wie die Zieldatei heißen soll. Falls die Zieldatei nicht existiert, wird diese erzeugt. Andernfalls wird diese Datei einfach überschrieben, da der Modus "w+" verwendet wurde. Hier wird außerdem der binäre Modus eingesetzt, da der Inhalt in diesem Fall beim Kopieren nicht von Interesse ist. Unter UNIX/Linux hat das b für den Binärmodus keine Bedeutung und wird somit ignoriert:

ziel = fopen(name_z, "w+b");

Anschließend wird überprüft, ob die Datei zum Schreiben im Binärmodus geöffnet werden konnte. Danach kann zeichenweise von der Quelldatei gelesen und in die Zieldatei geschrieben werden:

while( (c=getc(quelle)) != EOF)
   putc(c,ziel);

Wenn alles problemlos verlaufen ist, wurde eine exakte Kopie der Quelldatei erstellt mit dem Namen, der als Zieldatei angegeben wurde.

Dazu ein weiteres Beispiel, wann eine zeichenweise Abarbeitung von Daten sinnvoller erscheint. Jeder, der an einer Webseite arbeitet, kennt das Problem: Viel Text muss ins HTML-Format konvertiert werden. Wird dabei einmal das Zeichen '<' vergessen, welches einen HTML-Tag eröffnet, ist manchmal der vollständige Text bis zum nächsten mit '>' schließenden Tag futsch.

Das folgende Programm soll alle Sonderzeichen ins HTML-Format konvertieren. Folgende Regeln gelten:

Ersetze das Zeichen ä durch die Zeichenfolge &auml;
Ersetze das Zeichen Ä durch die Zeichenfolge &Auml;
Ersetze das Zeichen ö durch die Zeichenfolge &ouml;
Ersetze das Zeichen Ö durch die Zeichenfolge &Ouml;
Ersetze das Zeichen ü durch die Zeichenfolge &uuml;
Ersetze das Zeichen Ü durch die Zeichenfolge &Uuml;
Ersetze das Zeichen ß durch die Zeichenfolge &szlig;
Ersetze das Zeichen < durch die Zeichenfolge &lt;
Ersetze das Zeichen > durch die Zeichenfolge &gt;
Ersetze das Zeichen & durch die Zeichenfolge &amp;
Ersetze das Zeichen " durch die Zeichenfolge &quot;

Hier der Quellcode dazu:

/* txt2html_example.c */
#include <stdio.h>
#include <stdlib.h>
/* nchars = Anzahl der Zeichen */
/* tag    = Sonderzeichen in HTML */
/* ziel   = Datei, in die geschrieben wird */
void sonderzeichen(int nchars, char *tag, FILE *ziel) {
   int i;
   char zeichen;
   for(i = 0; i < nchars; i++) {
      zeichen = tag[i];
      putc(zeichen, ziel);
   }
}
int main(int argc, char **argv) {
   FILE *q, *z;
   int zeichen;
   if(argc < 3) {
      printf("Benutzung : %s quelle ziel\n", *argv);
      return EXIT_FAILURE;
   }
   q = fopen(argv[1], "r");
   z = fopen(argv[2], "w");
   if(q == NULL || z == NULL) {
      printf("Fehler bei Oeffnen einer Datei ...\n");
      return EXIT_FAILURE;
   }
   while((zeichen=getc(q)) != EOF) {
      if(zeichen=='<')
         sonderzeichen(4,"&lt;", z);
      else if(zeichen=='>')
         sonderzeichen(4,"&gt;", z);
      else if(zeichen=='\"')
         sonderzeichen(6,"&quot;",z);
      else if(zeichen=='&')
         sonderzeichen(5,"&amp;",z);
      else if(zeichen=='ä')
         sonderzeichen(6 ,"&auml;",z);
      else if(zeichen=='Ä')
         sonderzeichen(6 ,"&Auml;",z);
      else if(zeichen=='ö')
         sonderzeichen(6 ,"&ouml;",z);
      else if(zeichen=='Ö')
         sonderzeichen(6 ,"&Ouml;",z);
      else if(zeichen=='ü')
         sonderzeichen(6 ,"&uuml;",z);
      else if(zeichen=='Ü')
         sonderzeichen(6 ,"&Uuml;",z);
      else if(zeichen=='ß')
         sonderzeichen(6 ,"&szlig;",z);
      else
         putc(zeichen, z);
   }
   return EXIT_SUCCESS;
}

Schon wurde mit ein paar Zeilen Code ein Text2Html-Konverter in einer Light-Version geschrieben.

 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de