1 Theorie | ||
→ | 1.2 Häufig auftretende Problemstellungen | |
→ | 1.2.2 Dateien lesen und schreiben |
Um die Standard-Ein- und Ausgabe nutzen zu können, wird die
Header-Datei "stdio.h" benötigt.
Am Anfang des Quelltextmodules muss somit
#include <stdio.h>
stehen.
Die Funktionen zur Datei-Ein- und Ausgabe liefern bzw. verwenden Zeiger auf den Datentyp FILE. Es handelt sich hierbei um einen struct. Der Inhalt des struct ist systemabhängig und für uns uninteressant. Ein direkter Zugriff auf Komponenten des struct darf nicht erfolgen, der struct wird ausschließlich über die in stdio.h deklarierten Funktionen benutzt.
Die C-Runtime-Library sorgt dafür, dass folgende FILE-Zeiger zur Verfügung stehen:
Name | Benutzung |
---|---|
stdin | Standardeingabe. Hier können die vom Nutzer getätigten Eingaben gelesen werden. |
stdout | Standardausgabe. Die "normalen" Ausgaben werden normalerweise auf dem Bildschirm dargestellt. |
stderr | Standardfehlerausgabe. Fehlermeldungen sollten über dieses FILE ausgegeben werden, sie erscheinen auch dann auf dem Bildschirm, wenn die Standardausgabe umgeleitet wurde. |
Diese Datenströme sind bereits geöffnet und verfügbar, wenn die Abarbeitung der main()-Funktion beginnt.
Um eine Datei zu lesen oder zu schreiben, muss sie zunächst mit der Funktion
FILE * fopen(const char *path, const char *mode);
geöffnet werden.
Die Argumente sind zwei Strings:
Bei Erfolg gibt die Funktion einen Zeiger auf eine neu angelegte
FILE-Struktur zurück. Im Fehlerfall (z.B. eine zu lesende Datei
existiert gar nicht oder eine zu schreibende Datei kann nicht
angelegt werden) gibt die Funktion NULL zurück.
Das Ergebnis der Funktion muss also getestet werden, bevor es
verwendet werden kann.
Eine erfolgreich geöffnete Datei muss nach Verwendung wieder mit
fclose() geschlossen werden.
Eine erfolgreich geöffnete Datei muss nach der Verwendung mit
int fclose(FILE *fp);
geschlossen werden. Der FILE-Zeiger fp ist der Zeiger, der von der Funktion fopen() zurückgegeben wurde.
Bei Erfolg gibt die Funktion 0 zurück. Im Fehlerfall wird die
Variable errno gesetzt und EOF zurückgegeben.
EOF ist eine in stdio.h definierte Präprozessor-Konstante, die
meist auf -1 definiert ist. Sie wird von den Funktionen der
Standard-Ein- und Ausgabe häufig verwendet, um Fehler bei der
Ausgabe oder das Erreichen des Dateiendes bei der Eingabe (end of
file) zu signalisieren.
Ein möglicher Fehler ist z.B. wenn beim Schließen einer zum
Schreiben geöffneten Datei nicht alle Daten aus dem Puffer auf die
Festplatte geschrieben werden konnten, weil der Datenträger voll
ist. Darüber hinaus sind noch weitere Fehler möglich.
Mit
int fputc(int c, FILE *fp);
wird ein einzelnes Zeichen geschrieben. Für Daten, die als char
vorliegen, muss die Konvertierung zu int über den Zwischenschritt
unsigned char erfolgen.
Ausnahme: Wenn bereits bekannt ist, dass der Hexadezimal-Wert des
Buchstaben im Bereich 0x00...0x7F liegt.
Die Funktion gibt bei Erfolg 0 zurück, im Fehlerfall EOF.
Mit
int fputs(const char *s, FILE *fp);
wird der String s in die Datei fp geschrieben.
Dabei wird nicht automatisch ein Newline angehangen, der
String wird nur genau so geschrieben, wie er ist.
Die Funktion gibt bei Erfolg 0 zurück, bei Fehler EOF.
Mit
int fprintf(FILE *fp, const char *format, ...);
erfolgt eine formatierte Ausgabe (file print formatted).
Die Funktion arbeitet analog zur bereits besprochenen Funktion printf(). Die Ausgabe erfolgt hier aber nicht in die Standardausgabe, sondern in die angegebene Datei fp.
Die Funktion gibt die Anzahl der geschriebenen Bytes zurück, im Fehlerfall eine negative Zahl.
Formatierte Ausgabe bedeutet hier, dass vorgegebener konstanter
Text mit zur Laufzeit erzeugten Daten kombiniert wird. Der
konstante vorgegebene Text steht im format-String, für die
auszugebenden Daten stehen im format-String Platzhalter. Die
auszugebenden Daten stehen im fprintf()-Aufruf nach dem
format-String (also anstelle der Auslassung ...).
Die Platzhalter müssen in Anzahl und Reihenfolge mit den
auszugebenden Daten übereinstimmen.
Die Funktion fprintf() bietet die gleiche Flexibilität
wie printf(). Wird diese Funktion benutzt, wird beim Linken
eine große Anzahl Bibliotheksmodule aus der Laufzeitbibliothek mit
einbezogen.
Dies ist auf gängigen Desktop- und Serverbetriebssystemen kein
Problem. Auf Mikrocontrollern oder Embedded-Systemen steht jedoch
meist nur limitiert Hauptspeicher zur Verfügung.
Unter Windows steht eine neuere Funktion zum Öffnen von Dateien zur Verfügung, diese soll u.a. sicherer sein als fopen():
errno_t fopen_s(FILE **fpptr, const char *path, const char *mode);
Bei Erfolg gibt die Funktion den Wert 0 zurück und setzt den
FILE-Zeiger, dessen Adresse als fpptr übergeben wurde.
Bei Fehlern wird ein Fehlercode zurückgegeben.
Es muss also überprüft werden, ob der Rückgabewert 0 war, bevor der
FILE-Zeiger verwendet werden kann.
Microsoft propagiert, nur noch diese neue
Funktion zu nutzen und gibt bei Verwendung von fopen()
Warnungen aus.
Die Warnungen für fopen() können deaktiviert werden, indem
vor Einbindung des Headers stdio.h die Konstante
_CRT_SECURE_NO_WARNINGS auf einen Wert ungleich 0 definiert wird
(siehe nachfolgender Quelltext ex023.c).
/** @file ex023.c Demo-Programm fuer Schreiben einer Text-Datei.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#ifdef _WIN32
/** Benutzung von fopen() unter Windows zulassen. */
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#ifdef _WIN32
#include <process.h>
#endif
/** Dateiname der zu schreibenden Datei.
*/
#ifdef _WIN32
static const char filename[] = { "C:\\Temp\\testfile.txt" };
#else
static const char filename[] = { "testfile.txt" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
FILE *outf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
int i = 5; /* Variable fuer Testzwecke */
outf = fopen(filename, "w");
if (NULL != outf) {
/* Erfolg im Rueckgabecode vermerken */
exc = EXIT_SUCCESS;
/* Falls Schreiben der Textzeile fehlschlaegt, Misserfolg */
if (EOF == fputs("Dies ist ein Test-String", outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben des Newline fehlschlaegt, Misserfolg */
if (EOF == fputc('\n', outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben der formatierten Ausgabe fehlschlaegt, Misserfolg */
if (0 > fprintf(outf, "Der Wert der Variablen ist %d\n", i)) {
exc = EXIT_FAILURE;
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 != fclose(outf)) {
exc = EXIT_FAILURE;
}
outf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
/** @file ex024.c Demo-Programm fuer Schreiben einer Text-Datei
unter Windows.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#ifndef _WIN32
error "Dieses Programm kann nur unter Windows erstellt werden!"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
/** Dateiname der zu schreibenden Datei.
*/
static const char filename[] = { "C:\\Temp\\testfile.txt" };
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
FILE *outf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
int i = 5; /* Variable fuer Testzwecke */
int errc = 0; /* Ergebnis von fopen_s() */
errc = fopen_s(&outf, filename, "w");
if (0 == errc) {
/* Erfolg im Rueckgabecode vermerken */
exc = EXIT_SUCCESS;
/* Falls Schreiben der Textzeile fehlschlaegt, Misserfolg */
if (EOF == fputs("Dies ist ein Test-String", outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben des Newline fehlschlaegt, Misserfolg */
if (EOF == fputc('\n', outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben der formatierten Ausgabe fehlschlaegt, Misserfolg */
if (0 > fprintf(outf, "Der Wert der Variablen ist %d\n", i)) {
exc = EXIT_FAILURE;
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 != fclose(outf)) {
exc = EXIT_FAILURE;
}
outf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Um den Quelltext übersichtlich zu halten, versucht man, bedingte
Compilierung von Code zu minimieren und Code zur Behandlung von
Portabilitätsproblemen an bestimmten Stellen zu bündeln.
Code mit bedingter Compilierung wird in Funktionen zusammengefasst,
welche in Bibliotheks-Modulen oder ähnlich wiederverwertbaren
Modulen stehen.
Im Beispiel stellt das Modul he-file.c die Funktionen
hsm_et_file_open() und hsm_et_file_close() zur
Verfügung, die Prototypen stehen in he-file.h. In der
Funktion hsm_et_file_open() wird bedingte Compilierung
eingesetzt, um entweder fopen_s() oder fopen() zu
verwenden. Beide Funktionen geben bei Fehlern entsprechende
Meldungen aus.
Um das Programm ex025 zu erstellen, werden die Quelltextmodule
benötigt.
/** @file ex025.c Demo-Programm fuer Schreiben einer Text-Datei,
portabel mit he-file Modul.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include "he-conf.h"
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_PROCESS_H
#include <process.h>
#endif
#include "he-file.h"
/** Dateiname der zu schreibenden Datei.
*/
#if HE_ON_WINDOWS
static const char filename[] = { "C:\\Temp\\testfile.txt" };
#else
static const char filename[] = { "testfile.txt" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
FILE *outf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
int i = 5; /* Variable, wird ausgegeben. */
outf = hsm_et_file_open(filename, "w", NULL);
if (NULL != outf) {
/* Erfolg im Rueckgabecode vermerken */
exc = EXIT_SUCCESS;
/* Falls Schreiben der Textzeile fehlschlaegt, Misserfolg */
if (EOF == fputs("Dies ist ein Test-String", outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben des Newline fehlschlaegt, Misserfolg */
if (EOF == fputc('\n', outf)) {
exc = EXIT_FAILURE;
}
/* Falls Schreiben der formatierten Ausgabe fehlschlaegt, Misserfolg */
if (0 > fprintf(outf, "Der Wert der Variablen ist %d\n", i)) {
exc = EXIT_FAILURE;
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 >= hsm_et_file_close(outf, filename, NULL)) {
exc = EXIT_FAILURE;
}
outf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Mit der Funktion
size_t fwrite(const void *ptr, size_t elsize, size_t count, FILE *fp);
werden binäre Daten in die Datei geschrieben.
Das Argument ptr ist die Anfangsadresse des
Speicherbereiches, der die Daten enthält.
Das Argument elsize gibt die Größe eines einzelnen
Datensatzes an, count ist die Anzahl der Datensätze.
Die Funktion gibt die Anzahl der geschriebenen Datensätze zurück, bei fehlerfreiem Schreiben ist diese gleich count.
Das Beispielprogramm schreibt die Daten des Rechteckes re
in die Datei "datafile.dat".
Für das Öffnen und Schließen der Datei stehen hier prinzipiell
dieselben drei Möglichkeiten (fopen(), fopen_s() und
hsm_et_file_open()) zur Verfügung wie beim Schreiben von Text. Im
Beispiel wird wieder der Portabilitätslayer verwendet.
Soll das Programm auch unter Windows benutzt werden, muss als Modus
beim Öffnen der Datei "wb" verwendet werden, nicht "w".
Um das Programm ex026 zu erstellen, werden die folgenden Quelltextmodule verwendet:
/** @file ex026.c Demo-Programm fuer Schreiben einer Binaer-Datei,
portabel mit he-file Modul.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include "he-conf.h"
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_PROCESS_H
#include <process.h>
#endif
#include "he-file.h"
/** Koordinaten fuer einen Punkt.
*/
typedef struct {
double x; /**< x-Koordinate. */
double y; /**< y-Koordinate. */
} PUNKT;
/** Achsenparalleles Rechteck.
*/
typedef struct {
PUNKT lu; /**< Eckpunkt links unten. */
PUNKT ro; /**< Eckpunkt rechts oben. */
} RECHTECK;
/** Rechteck-Daten.
*/
const RECHTECK re = { { 1.0, 2.0 }, { 3.0, 4.0} };
/** Dateiname der zu schreibenden Datei.
*/
#if HE_ON_WINDOWS
static const char filename[] = { "C:\\Temp\\datafile.dat" };
#else
static const char filename[] = { "datafile.dat" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
FILE *outf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
size_t res; /* Ergebnis von fwrite() */
outf = hsm_et_file_open(filename, "wb", NULL);
if (NULL != outf) {
/* Erfolg im Rueckgabecode vermerken */
exc = EXIT_SUCCESS;
/* Wenn weniger als ein Rechteck geschrieben wurde, trat Fehler auf */
res = fwrite(&re, sizeof(RECHTECK), 1, outf);
if (1 > res) {
exc = EXIT_FAILURE;
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 >= hsm_et_file_close(outf, filename, NULL)) {
exc = EXIT_FAILURE;
}
outf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Mit der Funktion
int fgetc(FILE *fp);
wird ein Byte aus der Datei gelesen. Die Funktion gibt einen nichtnegativen Wert (0x00...0xFF) bei Erfolg zurück, EOF bei Fehler.
Um eine ganze Datei zeichenweise zu verarbeiten, wird in einer Schleife fgetc() immer wieder aufgerufen, bis der Wert EOF zurückgegeben wird.
Im Beispiel wird die zuvor angelegte Datei "testfile.txt"
zeichenweise eingelesen und verarbeitet.
Alle Zeichen werden in die Standardausgabe ausgegeben.
Um das Programm ex027 zu erstellen, werden die folgenden Quelltextmodule benötigt:
/** @file ex025.c Demo-Programm fuer Schreiben einer Text-Datei,
portabel mit he-file Modul.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include "he-conf.h"
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_PROCESS_H
#include <process.h>
#endif
#include "he-file.h"
/** Dateiname der zu schreibenden Datei.
*/
#if HE_ON_WINDOWS
static const char filename[] = { "C:\\Temp\\testfile.txt" };
#else
static const char filename[] = { "testfile.txt" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
FILE *inf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
int c; /* Zeichen, das eingelesen wird. */
inf = hsm_et_file_open(filename, "r", NULL);
if (NULL != inf) {
/* Erfolg im Rueckgabewert vermerken */
exc = EXIT_SUCCESS;
/* Alle Zeichen aus Datei einlesen und auf Standardausgabe ausgeben */
do {
c = fgetc(inf);
if (EOF != c) {
fputc(c, stdout);
}
} while (EOF != c);
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 >= hsm_et_file_close(inf, filename, NULL)) {
exc = EXIT_FAILURE;
}
inf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Die Funktion
char *fgets(char *s, int size, FILE *fp);
versucht, eine Textzeile aus der Datei fp in den Puffer
einzulesen, dessen Anfangsadresse durch s und dessen Größe
durch size gegeben ist.
Die einzulesende Textzeile erstreckt sich bis zum nächsten Newline
bzw. bis zum Dateiende. Das Newline wird mit in den Puffer
übernommen.
Ist die Textzeile zu lang für den Puffer, werden maximal
size-1 Zeichen gelesen.
Bei Erfolg ist der String im Puffer Null-terminiert.
Die Funktion gibt bei Erfolg die Adresse s zurück, bei
Fehler (z.B. Dateiende erreicht) NULL.
Nach dem Einlesen einer Zeile kann diese analysiert und
verarbeitet werden. Kommt es dabei zu einem Fehler (z.B. die Zeile
entspricht nicht der erwarteten Syntax), sollte die Fehlermeldung
neben der Art des Fehlers auch den Dateinamen und die Zeilennummer
der betreffenden Zeile enthalten.
Die Fehlermeldungen werden nach stderr ausgegeben. Der Stil sollte
dabei dem Muster
Eingabedatei:Zeilennummer: Schweregrad: Text
folgen, also z.B.:
Eingabe.txt:1: Fehler: Der Anlagebetrag darf nicht negativ sein!
Im Beispiel wird die zuvor angelegte Datei "testfile.txt"
zeilenweise eingelesen und verarbeitet.
Die Zeilen werden auf die Standardausgabe ausgegeben, die
Zeilennummer wird vorangestellt.
Um das Programm ex028 zu erstellen, werden die folgenden Quelltextmodule benötigt:
/** @file ex025.c Demo-Programm fuer Schreiben einer Text-Datei,
portabel mit he-file Modul.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include "he-conf.h"
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_PROCESS_H
#include <process.h>
#endif
#include "he-file.h"
/** Dateiname der zu schreibenden Datei.
*/
#if HE_ON_WINDOWS
static const char filename[] = { "C:\\Temp\\testfile.txt" };
#else
static const char filename[] = { "testfile.txt" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
char buf[1024]; /* Puffer zum Einlesen */
FILE *inf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
int lineno = 0; /* Aktuelle Zeilennummer. */
inf = hsm_et_file_open(filename, "r", NULL);
if (NULL != inf) {
/* Erfolg im Rueckgabewert vermerken */
exc = EXIT_SUCCESS;
/* Alle Zeichen aus Datei einlesen und auf Standardausgabe ausgeben */
while (fgets(buf, sizeof(buf), inf)) {
printf("Zeile %5d: ", ++lineno);
fputs(buf, stdout);
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 >= hsm_et_file_close(inf, filename, NULL)) {
exc = EXIT_FAILURE;
}
inf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Mit der Funktion
int fscanf(FILE *fp, char *format, ...);
können Daten aus einer Textdatei entsprechend dem
format-String eingelesen werden. Der verarbeitete Text wird
entsprechend den Platzhaltern im Formatstring in die gewünschten
Datentypen umgewandelt und an den angegebenen Adressen
gespeichert.
Die Funktion gibt die Anzahl erfolgreich bearbeiteter Platzhalter
zurück.
Die Eingabeverarbeitung mit fscanf() weist die bereits in Ausgabe mit printf, Eingabe mit scanf beschriebenen Probleme auf.
Mit der Funktion
size_t fread(void *ptr, size_t elsize, size_t count, FILE *fp);
werden binäre Daten in einen Puffer eingelesen, der an der
Adresse ptr beginnt. Die Größe des Puffers ist durch die
Datensatzgröße elsize und die maximale Datensatzanzahl
count gegeben.
Die Funktion gibt die Anzahl erfolgreich eingelesener Datensätze
zurück. Diese Anzahl kann auch geringer als count sein, z.B.
wenn die Datei weniger Datensätze enthält.
Im Beispiel wird ein RECHTECK-Datensatz aus der zuvor angelegten Datei "datafile.dat" in die Variable re eingelesen. Bei Erfolg werden die Rechteck-Daten auf die Standardausgabe ausgegeben.
Zum Erstellen des Programmes ex029 werden die folgenden Quelltextmodule benötigt:
/** @file ex029.c Demo-Programm fuer Lesen einer Binaer-Datei,
portabel mit he-file Modul.
*/
/* Copyright (C) 2014-2017 - HS Schmalkalden. All rights reserved. */
#include "he-conf.h"
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_PROCESS_H
#include <process.h>
#endif
#include "he-file.h"
/** Koordinaten fuer einen Punkt.
*/
typedef struct {
double x; /**< x-Koordinate. */
double y; /**< y-Koordinate. */
} PUNKT;
/** Achsenparalleles Rechteck.
*/
typedef struct {
PUNKT lu; /**< Eckpunkt links unten. */
PUNKT ro; /**< Eckpunkt rechts oben. */
} RECHTECK;
/** Dateiname der zu lesenden Datei.
*/
#if HE_ON_WINDOWS
static const char filename[] = { "C:\\Temp\\datafile.dat" };
#else
static const char filename[] = { "datafile.dat" };
#endif
/** Hauptprogramm.
@return 0 bei Erfolg, alle anderen Werte bedeuten Fehler.
*/
int
main(void)
{
RECHTECK re;
FILE *inf = NULL; /* Datei-Zeiger */
int exc = EXIT_FAILURE; /* Exit-Code des Programmes. */
size_t res; /* Ergebnis von fread() */
inf = hsm_et_file_open(filename, "rb", NULL);
if (NULL != inf) {
/* Erfolg im Rueckgabecode vermerken */
exc = EXIT_SUCCESS;
/* Versuchen, einen RECHTECK-Datensatz einzulesen */
res = fread(&re, sizeof(RECHTECK), 1, inf);
/* Wenn res = 1 ist, waren wir erfolgreich */
if (0 < res) {
printf(
"Erfolg. Rechteck gelesen.\nx1=%lg\ny1=%lg\nx2=%lg\ny2=%lg\n",
re.lu.x, re.lu.y, re.ro.x, re.ro.y
);
}
else {
fputs("FEHLER: Kein Rechteck gelesen!\n", stderr);
fflush(stderr);
exc = EXIT_FAILURE;
}
/* Falls Schliessen der Datei fehlschlaegt, Misserfolg */
if (0 >= hsm_et_file_close(inf, filename, NULL)) {
exc = EXIT_FAILURE;
}
inf = NULL;
}
exit(exc); return exc;
}
/* vim: set ai sw=4 ts=4 expandtab : */
Die Funktion
int feof(FILE *fp);
testet, ob das Dateiende bereits erreicht wurde. Gibt die
Funktion 0 zurück, können weiter Daten von Datei eingelesen
werden.
Alle anderen Rückgabewerte zeigen an, dass das Dateiende erreicht
wurde.
Quelle: CERT C Coding Standard 〈1〉
FILE *fp = NULL; fp = fopen(..., ...); if (NULL != fp) { /* Verwendung der Datei hier */ fclose(fp); fp = NULL; } else { /* Fehlermeldung, Datei kann nicht geoeffnet werden! */ }bzw.
FILE *fp = NULL; int errc = 0; errc = fopen_s(&fp, ..., ...); if (0 == errc) { /* Verwendung der Datei hier */ fclose(fp); fp = NULL; } else { /* Fehlermeldung, Datei kann nicht geoeffnet werden! */ }oder
#include "he-file.h" FILE *fp = NULL; fp = hsm_et_file_open(..., ...); if (NULL != fp) { /* Verwendung der Datei hier */ hsm_et_file_close(fp, ..., ...); } else { /* Fehlermeldung, Datei kann nicht geoeffnet werden! */ }geschrieben werden. Damit wird sichergestellt, dass
1 | http://www.securecoding.cert.org |