|
|
I-PROGRAMMIEREN1 WS 0203 - Vorlesung mit Übung
|
Bisher wurden drei Möglichkeiten vorgestellt, wie ein C-Programm mit seiner Umgebung Daten austauschen kann:
Über den Bildschirm (bekannt als 'stdout').
Durch Argumente auf der Befehlszeile
Mittels der Tastatur (bekannt als 'stdin')
Eine vierte Möglichkeit, mit der Umgebung Daten auszutauschen, ist jene über das Lesen und Schreiben von Dateien. Dies soll Gegenstand der heutigen Vorlesung sein.
Bei der Behandlung der Dateioperationen unter C muss man sich vor Augen halten, dass in C der Austausch von Daten zwischen Geräten wie Tastatur, Bildschirm, Plattenspeichern, und allen anderen peripheren Geräten in einheitlicher Weise mit dem Konzept der Streams beschrieben wird. Dies bedeutet, ob Datei, Device oder was auch immer, in C wird ein Stream geöffnet (mit fopen()), und zwar entweder zum
Lesen ("r", read),
zum Anhängen ("a", append) oder
zum Schreiben ("w", write).
Fügt man ein "b" an, dann bedeutet dies beim Modus, dass der Stream nicht als Text-Stream geöffnet werden soll, sondern als Bit-Stream.
Es gibt drei Standard-Streams, die immer geöffnet werden:
stdin für die Standardeingabe von der Tastatur,
stdout für die Standardausgabe auf den Bildschirm und
stderr, der Standardfehlerkanal, der auch auf den Bildschirm geleitet wird.
Man kann allerdings weitere Streams erzeugen und sie mit einem Namen belegen. Dabei muss man beachten, dass man die maximale Länge von Namen (FILENAME_MAX) nicht überschreitet.
Liefert fopen einen NULL-Pointer zurück, dann ist etwas falsch gelaufen und man sollte sofort klären (mit der Funktion ferror), was geschehen ist. Andernfalls kann man weiter arbeiten. Der Filepointer fp, der verschieden ist von NULL, ist ein Filedescriptor, der von anderen Funktionen als Name des Streams solange benutzt werden kann, bis die Funktion fclose(fp) ihn wieder 'ausser Kraft setzt'.
Ist es gelungen, einen Stream erfolgreich z.B. zum Lesen zu öffnen, dann kann man mit der Funktion fgetc(fp) oder dem Makro getc(fp) den Inhalt des Streams zeichenweise auslesen (die C-Bibliothek hällt weitere Funktionen zum Lesen bereit). Entdecken fgetc() oder getc() das Ende des Streams oder einen Fehler, dann liefern sie EOF= -1 als Ergebnis zurück, andernfalls den Integerwert des gelesenen Zeichens.
Dateien in C (Anmerkung: die Position des Zeichens '+' im Feld 'MODE' von fopen() ist 'zwischen' den beiden anderen Optionen, nicht davor, wie im Bild fälschlich angegeben)
Wer genauere Informationen zu den einzelnen Funktionen haben will, kann unter UNIX bzw. LINUX diese einfach per 'man FUNKTIONSNAME' abfragen. Auf die Frage 'man fopen' z.B. bekommt man folgende Informationen:
NAME
fopen, fdopen, freopen - stream open functions
SYNOPSIS
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fildes, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);
DESCRIPTION
The fopen function opens the file whose name is the string pointed to by path and
associates a stream with it.
The argument mode points to a string beginning with one of the following sequences
(Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the beginning of
the file.
r+ Open for reading and writing. The stream is positioned at the beginning of
the file.
w Truncate file to zero length or create text file for writing. The stream is
positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does not exist,
otherwise it is truncated. The stream is positioned at the beginning of the
file.
a Open for appending (writing at end of file). The file is created if it does
not exist. The stream is positioned at the end of the file.
a+ Open for reading and appending (writing at end of file). The file is cre
ated if it does not exist. The stream is positioned at the end of the file.
The mode string can also include the letter ``b'' either as a last character or as
a character between the characters in any of the two-character strings described
above. This is strictly for compatibility with ANSI X3.159-1989 (``ANSI C'') and
has no effect; the ``b'' is ignored on all POSIX conforming systems, including
Linux. (Other systems may treat text files and binary files differently, and
adding the ``b'' may be a good idea if you do I/O to a binary file and expect that
your program may be ported to non-Unix environments.)
Any created files will have mode S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
(0666), as modified by the process' umask value (see umask(2).
Reads and writes may be intermixed on read/write streams in any order. Note that
ANSI C requires that a file positioning function intervene between output and
input, unless an input operation encounters end-of-file. (If this condition is not
met, then a read is allowed to return the result of writes other than the most
recent.) Therefore it is good practice (and indeed sometimes necessary under
Linux) to put an fseek or fgetpos operation between write and read operations on
such a stream. This operation may be an apparent no-op (as in fseek(..., 0L,
SEEK_CUR) called for its synchronizing side effect.
Opening a file in append mode (a as the first character of mode) causes all subse
quent write operations to this stream to occur at end-of-file, as if preceded by an
fseek(stream,0,SEEK_END);
call.
The fdopen function associates a stream with the existing file descriptor, fildes.
The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be
compatible with the mode of the file descriptor. The file position indicator of
the new stream is set to that belonging to fildes, and the error and end-of-file
indicators are cleared. Modes "w" or "w+" do not cause truncation of the file.
The file descriptor is not dup'ed, and will be closed when the stream created by
fdopen is closed. The result of applying fdopen to a shared memory object is unde
fined.
The freopen function opens the file whose name is the string pointed to by path and
associates the stream pointed to by stream with it. The original stream (if it
exists) is closed. The mode argument is used just as in the fopen function.
The file descriptor is not dup'ed, and will be closed when the stream created by
fdopen is closed. The result of applying fdopen to a shared memory object is unde
fined.
The freopen function opens the file whose name is the string pointed to by path and
associates the stream pointed to by stream with it. The original stream (if it
exists) is closed. The mode argument is used just as in the fopen function. The
primary use of the freopen function is to change the file associated with a stan
dard text stream (stderr, stdin, or stdout).
RETURN VALUE
Upon successful completion fopen, fdopen and freopen return a FILE pointer. Other
wise, NULL is returned and the global variable errno is set to indicate the error.
ERRORS
EINVAL The mode provided to fopen, fdopen, or freopen was invalid.
The fopen, fdopen and freopen functions may also fail and set errno for any of the
errors specified for the routine malloc(3).
The fopen function may also fail and set errno for any of the errors specified for
the routine open(2).
The fdopen function may also fail and set errno for any of the errors specified for
the routine fcntl(2).
The freopen function may also fail and set errno for any of the errors specified
for the routines open(2), fclose(3) and fflush(3).
CONFORMING TO
The fopen and freopen functions conform to ANSI X3.159-1989 (``ANSI C''). The
fdopen function conforms to IEEE Std1003.1-1988 (``POSIX.1'').
Frage nach 'fclose' mit 'man fclose':
NAME
fclose - close a stream
SYNOPSIS
#include <stdio.h>
int fclose(FILE *stream);
DESCRIPTION
The fclose function dissociates the named stream from its underlying file or set of
functions. If the stream was being used for output, any buffered data is written
first, using fflush(3).
RETURN VALUE
Upon successful completion 0 is returned. Otherwise, EOF is returned and the
global variable errno is set to indicate the error. In either case any further
access (including another call to fclose()) to the stream results in undefined
behaviour.
ERRORS
EBADF The filedescriptor underlying stream is not valid.
The fclose function may also fail and set errno for any of the errors specified for
the routines close(2), write(2) or fflush(3).
NOTES
Note that fclose only flushes the user space buffers provided by the C library. To
ensure that the data is physically stored on disk the kernel buffers must be
flushed too, e.g. with sync(2) or fsync(2).
CONFORMING TO
The fclose function conforms to ANSI X3.159-1989 (``ANSI C'').
SEE ALSO
close(2), fcloseall(3), fflush(3), fopen(3), setbuf(3)
Auf die Frage 'man fgetc' z.B. bekommt man folgende Informationen:
NAME
fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings
SYNOPSIS
#include <stdio.h>
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c, FILE *stream);
DESCRIPTION
fgetc() reads the next character from stream and returns it as an unsigned char
cast to an int, or EOF on end of file or error.
getc() is equivalent to fgetc() except that it may be implemented as a macro which
evaluates stream more than once.
getchar() is equivalent to getc(stdin).
gets() reads a line from stdin into the buffer pointed to by s until either a ter
minating newline or EOF, which it replaces with '\0'. No check for buffer overrun
is performed (see BUGS below).
fgets() reads in at most one less than size characters from stream and stores them
into the buffer pointed to by s. Reading stops after an EOF or a newline. If a
newline is read, it is stored into the buffer. A '\0' is stored after the last
character in the buffer.
ungetc() pushes c back to stream, cast to unsigned char, where it is available for
subsequent read operations. Pushed - back characters will be returned in reverse
order; only one pushback is guaranteed.
ungetc() pushes c back to stream, cast to unsigned char, where it is available for
subsequent read operations. Pushed - back characters will be returned in reverse
order; only one pushback is guaranteed.
Calls to the functions described here can be mixed with each other and with calls
to other input functions from the stdio library for the same input stream.
For non-locking counterparts, see unlocked_stdio(3).
RETURN VALUE
fgetc(), getc() and getchar() return the character read as an unsigned char cast to
an int or EOF on end of file or error.
gets() and fgets() return s on success, and NULL on error or when end of file
occurs while no characters have been read.
ungetc() returns c on success, or EOF on error.
CONFORMING TO
ANSI - C, POSIX.1
BUGS
Never use gets(). Because it is impossible to tell without knowing the data in
advance how many characters gets() will read, and because gets() will continue to
store characters past the end of the buffer, it is extremely dangerous to use. It
has been used to break computer security. Use fgets() instead.
It is not advisable to mix calls to input functions from the stdio library with low
- level calls to read() for the file descriptor associated with the input stream;
the results will be undefined and very probably not what you want.
Das folgende einfache Beispiel demonstriert das Öffnen einer Textdatei zum Lesen mittels der Funktion fgetc().
/*************************
*
* i-progr1-th7-dateiread.c
*
* author: gdh
* first: ws01
* last: nov-11,02
*
* idea: Öffnen einer Datei zum Lesen im Textmodus
* Ausgabe auf Bildschirm
*
* - Das Programm erfragt vom Benutzer einen Dateinamen mit fgets()
* - Mit diesem Dateinamen wird dann die Datei zum Lesen geöfnet
* - Die geöffnete Datei wird mit fgetc() asugelesen und die gelesenen Werte werden in
* auf dem Bildschirm ausgegeben
*
* compilation: gcc -o dateiread dateiread.c
* usage: dateiread
*
***************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
main(void){
int c;
FILE *fp; /* Zeiger vom Typ FILE für Dateioperationen */
char dname[FILENAME_MAX]; /* Feld für Dateinamen mit maximal möglicher Länge */
/*****************************************/
/* ECKWERTE ZU FILENAME_MAX und FOPEN_MAX*/
/*****************************************/
printf("FOPEN_MAX = %d\n",FOPEN_MAX);
printf("FILENAME_MAX = %d\n",FILENAME_MAX);
/*********************************/
/* EINGABE DATEINAME */
/*********************************/
printf("BITTE DATEINAMN eingeben: ");
fgets(dname, FILENAME_MAX, stdin);
dname[strlen(dname)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */
/*********************************/
/* DATEI WIRD ZUM LESEN GEOEFFNET */
/*********************************/
errno = 0; /* errno ist Fehlervariable; wird vom System gesetzt, wenn Fehler */
fp = fopen(dname, "r");
if (errno != 0 ){
/******************************/
/* FEHLERBEHANDLUNG */
/******************************/
fprintf(stderr, "open_file(\"%s\") failed: %s\n", dname, strerror(errno));
} /* strerror() ist eine Fehlerfunktion, die die Fehlernummer kommentiert ausgibt */
else{
/*********************************/
/* AUSLESEN DER DATEI */
/*********************************/
c = fgetc(fp);
while (c != EOF){
printf("%c",c);
c = fgetc(fp);
}
}/* End of else */
/*********************************/
/* DATEI WIRD GESCHLOSSEN */
/*********************************/
printf("VOR SCHLIESSUNG DATEI\n");
errno =0;
if (fclose(fp) != 0) { fprintf(stderr, "close_file failed: %s\n", strerror(errno)); return (1); }
else { return (0); }
}
Im Programm wird die Fehlervariable 'errno' benutzt. Im Nicht-Fehlerfall hat sie den Wert '0' bzw. sie muss vor Benutzung von Funktionen, die Fehlermeldungen erzeugen können, explizit auf 0 gesetzt werden. Nach Aufruf einer Funktion, die Fehlermeldungen in errno setzen kann, ist errno abzufragen. Dazu kann man die Funktion strerror() benutzen; diese übersetzt die Fehlernummer in einen kurzen erklärenden Text und gibt diesen auf dem Bildschirm aus. Weitere erklärungen zu 'errno' und 'strerror()' kann man wieder über 'man ...' abfragen.
NAME errno - number of
last error
SYNOPSIS
#include <errno.h>
extern int errno;
DESCRIPTION
The integer errno is set by system calls (and some library functions) to indicate
what went wrong. Its value is significant only when the call returned an error
(usually -1), and a library function that does succeed is allowed to change errno.
Sometimes, when -1 is also a legal return value one has to zero errno before the
call in order to detect possible errors.
errno is defined by the ISO C standard to be a modifiable lvalue of type int, and
must not be explicitly declared; errno may be a macro. errno is thread-local; set
ting it in one thread does not affect its value in any other thread.
Valid error numbers are all non-zero; errno is never set to zero by any library
function. All the error names specified by POSIX.1 must have distinct values.
POSIX.1 (1996 edition) lists the following symbolic error names. Of these, EDOM
and ERANGE are in the ISO C standard. ISO C Amendment 1 defines the additional
error number EILSEQ for coding errors in multibyte or wide characters.
E2BIG Arg list too long
EACCES Permission denied
EAGAIN Resource temporarily unavailable
EBADF Bad file descriptor
EBADMSG
Bad message
EBUSY Resource busy
ECANCELED
Operation canceled
ECHILD No child processes
EDEADLK
Resource deadlock avoided
EDOM Domain error
EEXIST File exists
EFAULT Bad address
EFBIG File too large
EINPROGRESS
Operation in progress
EINTR Interrupted function call
EINVAL Invalid argument
EIO Input/output error
EISDIR Is a directory
EMFILE Too many open files
EMLINK Too many links
EMSGSIZE
Inappropriate message buffer length
ENAMETOOLONG
Filename too long
ENFILE Too many open files in system
ENODEV No such device
ENOENT No such file or directory
ENOEXEC
Exec format error
ENOLCK No locks available
ENOMEM Not enough space
ENOSPC No space left on device
ENOSYS Function not implemented
ENOTDIR
Not a directory
ENOTEMPTY
Directory not empty
ENOTSUP
Not supported
ENOTTY Inappropriate I/O control operation
ENXIO No such device or address
EPERM Operation not permitted
EPIPE Broken pipe
ERANGE Result too large
ENOTEMPTY
Directory not empty
ENOTSUP
Not supported
ENOTTY Inappropriate I/O control operation
ENXIO No such device or address
EPERM Operation not permitted
EPIPE Broken pipe
ERANGE Result too large
EROFS Read-only file system
ESPIPE Invalid seek
ESRCH No such process
ETIMEDOUT
Operation timed out
EXDEV Improper link
Many other error numbers are returned by various Unix implementations. System V
returns ETXTBSY (Text file busy) if one tries to exec() a file that is currently
open for writing. Linux also returns this error if one tries to have a file both
memory mapped with VM_DENYWRITE and open for writing.
SEE ALSO
perror(3), strerror(3)
Die Anfrage 'man strerror' liefert:
NAME
strerror, strerror_r - return string describing error code
SYNOPSIS
#include <string.h>
char *strerror(int errnum);
int strerror_r(int errnum, char *buf, size_t n);
DESCRIPTION
The strerror() function returns a string describing the error code passed in the
argument errnum, possibly using the LC_MESSAGES part of the current locale to
select the appropriate language. This string must not be modified by the applica
tion, but may be modified by a subsequent call to perror() or strerror(). No
library function will modify this string.
The strerror_r() function is similar to strerror(), but is thread safe. It returns
the string in the user-supplied buffer buf of length n.
RETURN VALUE
The strerror() function returns the appropriate error description string, or an
unknown error message if the error code is unknown. The value of errno is not
changed for a successful call, and is set to a nonzero value upon error. The str
error_r() function returns 0 on success and -1 on failure, setting errno.
ERRORS
EINVAL The value of errnum is not a valid error number.
ERANGE Insufficient storage was supplied to contain the error description string.
CONFORMING TO
SVID 3, POSIX, BSD 4.3, ISO/IEC 9899:1990 (C89).
SEE ALSO
errno(3), perror(3), strsignal(3)
In diesem Beispiel betrachten wir den Fall, dass man Text an eine Datei anhängen will. Falls die angegebene Datei noch nicht existiert, wird sie neu angelegt. Existiert sie, wird der Text automatisch an das aktuelle Ende der Datei angehängt. Nach der Eingabe wird ein Kontrollausdruck der neuen kompletten Datei gegeben. Zu diesem Zweck muss aber der Filepointer zunächst auf den Anfang der Datei zurückgesetzt werdem, damit der Kontrollausdruck vom Anfang der Datei liest. Die hierbei benutzten Befehle sinddie folgenden:
fgets(dname, FILENAME_MAX, stdin) zum Einlesen des Dateinamens von der Tastatur
fgets(texteingabe, TEXT_MAX, stdin) zum Einlesen der texteingabe von der Tastatur
fp = fopen(dname, "a+") zum Öffnen einer Datei im Modus 'Anhängen ('append') mit dem Zusatz ('+'), dass sie auch lesbar sein soll
fputs(texteingabe, fp) Schreiben des Textes aus der Variablen 'texteingabe' in die Datei
rewind(fp) Zurücksetzen des Filepointers auf den Anfang der Datei
Für mehr Informationen zu den Funktionen fputs() und rewind() siehe wieder die man-Einträge:
NAME
fputc, fputs, putc, putchar, puts - output of characters and strings
SYNOPSIS
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
DESCRIPTION
fputc() writes the character c, cast to an unsigned char, to stream.
fputs() writes the string s to stream, without its trailing '\0'.
putc() is equivalent to fputc() except that it may be implemented as a macro which
evaluates stream more than once.
putchar(c); is equivalent to putc(c,stdout).
puts() writes the string s and a trailing newline to stdout.
Calls to the functions described here can be mixed with each other and with calls
to other output functions from the stdio library for the same output stream.
For non-locking counterparts, see unlocked_stdio(3).
RETURN VALUE
fputc(), putc() and putchar() return the character written as an unsigned char cast
to an int or EOF on error.
puts() and fputs() return a non-negative number on success, or EOF on error.
CONFORMING TO
ANSI - C, POSIX.1
BUGS
It is not advisable to mix calls to output functions from the stdio library with
low - level calls to write() for the file descriptor associated with the same out
put stream; the results will be undefined and very probably not what you want.
SEE ALSO
write(2), ferror(3), fopen(3), fseek(3), fwrite(3), gets(3), scanf(3),
unlocked_stdio(3)
NAME
fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream
SYNOPSIS
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
DESCRIPTION
The fseek function sets the file position indicator for the stream pointed to by
stream. The new position, measured in bytes, is obtained by adding offset bytes to
the position specified by whence. If whence is set to SEEK_SET, SEEK_CUR, or
SEEK_END, the offset is relative to the start of the file, the current position
indicator, or end-of-file, respectively. A successful call to the fseek function
clears the end-of-file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream.
The ftell function obtains the current value of the file position indicator for the
stream pointed to by stream.
The rewind function sets the file position indicator for the stream pointed to by
stream to the beginning of the file. It is equivalent to:
(void)fseek(stream, 0L, SEEK_SET)
except that the error indicator for the stream is also cleared (see clearerr(3)).
The fgetpos and fsetpos functions are alternate interfaces equivalent to ftell and
fseek (with whence set to SEEK_SET), setting and storing the current value of the
file offset into or from the object referenced by pos. On some non-UNIX systems an
fpos_t object may be a complex object and these routines may be the only way to
portably reposition a text stream.
RETURN VALUE
The rewind function returns no value. Upon successful completion, fgetpos, fseek,
fsetpos return 0, and ftell returns the current offset. Otherwise, -1 is returned
and the global variable errno is set to indicate the error.
ERRORS
EBADF The stream specified is not a seekable stream.
EINVAL The whence argument to fseek was not SEEK_SET, SEEK_END, or SEEK_CUR.
The function fgetpos, fseek, fsetpos, and ftell may also fail and set errno for any
of the errors specified for the routines fflush(3), fstat(2), lseek(2), and mal
loc(3).
CONFORMING TO
The fgetpos, fsetpos, fseek, ftell, and rewind functions conform to ANSI
X3.159-1989 (``ANSI C'').
SEE ALSO
lseek(2), fseeko(3)
/*************************
*
* i-progr1-th7-dateiappend.c
*
* author: gdh
* first: -
* last: nov-12,02
*
* idea: Öffnen einer Datei zum Anhängen von Daten im Textmodus
*
* - Das Programm erfragt vom Benutzer einen Dateinamen mit fgets()
* - Dann wird eine Texteingabe angefordert
* - Mit dem Dateinamen wird dann die Datei zum Anhängen geöffnet
* - und der eingelesene Text wird an die Datei angehängt
*
* compilation: gcc -o dateiappend dateiappend.c
* usage: dateiappend
*
***************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define TEXT_MAX 1000
main(void){
int c,i;
FILE *fp; /* Zeiger vom Typ FILE für Dateioperationen */
char dname[FILENAME_MAX]; /* Feld für Dateinamen mit maximal möglicher Länge */
char texteingabe[TEXT_MAX]; /* Feld für TEXTEINGABE mit maximal möglicher Länge */
/*****************************************/
/* ECKWERTE ZU FILENAME_MAX und FOPEN_MAX*/
/*****************************************/
printf("FOPEN_MAX = %d\n",FOPEN_MAX);
printf("FILENAME_MAX = %d\n",FILENAME_MAX);
/*********************************/
/* EINGABE DATEINAME */
/*********************************/
printf("BITTE DATEINAMN eingeben: ");
fgets(dname, FILENAME_MAX, stdin);
dname[strlen(dname)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */
/*********************************/
/* EINGABE TEXT */
/*********************************/
printf("BITTE TEXT eingeben: ");
fgets(texteingabe, TEXT_MAX, stdin);
texteingabe[strlen(texteingabe)-1]='\0'; /* Steuerzeichen '\n' von fgets() durch '\0' ersetzen */
/***************************************/
/* DATEI WIRD ZUM ANHAENGEN GEOEFFNET */
/***************************************/
errno = 0; /* errno ist Fehlervariable; wird vom System gesetzt, wenn Fehler */
fp = fopen(dname, "a+"); /* Datei wird zum Anhängen und Lesen geöffnet */
if (errno != 0 ){
/******************************/
/* FEHLERBEHANDLUNG */
/******************************/
fprintf(stderr, "open_file(\"%s\") failed: %s\n", dname, strerror(errno));
} /* strerror() ist eine Fehlerfunktion, die die Fehlernummer kommentiert ausgibt */
else{
/************************************/
/* ANHAENGEN DER DATEN AN DIE DATEI */
/************************************/
printf("TEXT WIRD JETZT ABGESPEICHERT\n\n");
if( fputs(texteingabe, fp) == EOF ) printf("\n.\nERROR on writing the file\n\n");
/************************************/
/* AUSLESEN DER DATEI ZUR KONTROLLE */
/*************************************/
printf("AUSLESEN DER DATEI ZUR KONTROLLE\n\n");
rewind(fp); /* Setzt den Filepointer wieder auf den Anfang */
c = fgetc(fp);
while (c != EOF) {
printf("%c",c);
c = fgetc(fp);
}
}/* End of else */
/*********************************/
/* DATEI WIRD GESCHLOSSEN */
/*********************************/
printf("\n\nVOR SCHLIESSUNG DATEI\n");
errno =0;
if (fclose(fp) != 0) { fprintf(stderr, "close_file failed: %s\n", strerror(errno)); return (1); }
else { printf("\n\nNACH SCHLIESSUNG DER DATEI\n"); return (0); }
}
Es soll an dieser stelle nur darauf hingewiessen werden, dass man von C aus auch Dateien mit remove() entfernen bzw. mit rename() auch umbenennen kann.
NAME
rename - change the name or location of a file
SYNOPSIS
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
DESCRIPTION
rename renames a file, moving it between directories if required.
Any other hard links to the file (as created using link(2)) are unaffected.
If newpath already exists it will be atomically replaced (subject to a few condi
tions - see ERRORS below), so that there is no point at which another process
attempting to access newpath will find it missing.
If newpath exists but the operation fails for some reason rename guarantees to
leave an instance of newpath in place.
However, when overwriting there will probably be a window in which both oldpath and
newpath refer to the file being renamed.
If oldpath refers to a symbolic link the link is renamed; if newpath refers to a
symbolic link the link will be overwritten.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropri
ately.
ERRORS
EISDIR newpath is an existing directory, but oldpath is not a directory.
EXDEV oldpath and newpath are not on the same filesystem.
ENOTEMPTY or EEXIST
newpath is a non-empty directory, i.e., contains entries other than "." and
"..".
EBUSY The rename fails because oldpath or newpath is a directory that is in use by
some process (perhaps as current working directory, or as root directory, or
because it was open for reading) or is in use by the system (for example as
mount point), while the system considers this an error. (Note that there is
no requirement to return EBUSY in such cases - there is nothing wrong with
doing the rename anyway - but it is allowed to return EBUSY if the system
cannot otherwise handle such situations.)
EINVAL The new pathname contained a path prefix of the old, or, more generally, an
attempt was made to make a directory a subdirectory of itself.
EMLINK oldpath already has the maximum number of links to it, or it was a directory
and the directory containing newpath has the maximum number of links.
ENOTDIR
A component used as a directory in oldpath or newpath is not, in fact, a
directory. Or, oldpath is a directory, and newpath exists but is not a
directory.
EFAULT oldpath or newpath points outside your accessible address space.
EACCES Write access to the directory containing oldpath or newpath is not allowed
for the process's effective uid, or one of the directories in oldpath or
newpath did not allow search (execute) permission, or oldpath was a direc
tory and did not allow write permission (needed to update the .. entry).
EPERM or EACCES
The directory containing oldpath has the sticky bit set and the process's
effective uid is neither that of root nor the uid of the file to be deleted
nor that of the directory containing it, or newpath is an existing file and
the directory containing it has the sticky bit set and the process's effec
tive uid is neither that of root nor the uid of the file to be replaced nor
that of the directory containing it, or the filesystem containing pathname
does not support renaming of the type requested.
ENAMETOOLONG
oldpath or newpath was too long.
ENOENT A directory component in oldpath or newpath does not exist or is a dan
gling symbolic link.
ENOMEM Insufficient kernel memory was available.
EROFS The file is on a read-only filesystem.
ELOOP Too many symbolic links were encountered in resolving oldpath or newpath.
ENOSPC The device containing the file has no room for the new directory entry.
CONFORMING TO
POSIX, 4.3BSD, ANSI C
BUGS
On NFS filesystems, you can not assume that if the operation failed the file was
not renamed. If the server does the rename operation and then crashes, the
retransmitted RPC which will be processed when the server is up again causes a
failure. The application is expected to deal with this. See link(2) for a similar
problem.
SEE ALSO
link(2), unlink(2), symlink(2), mv(1)
NAME
remove - delete a name and possibly the file it refers to
SYNOPSIS
#include <stdio.h>
int remove(const char *pathname);
DESCRIPTION
remove deletes a name from the filesystem. It calls unlink for files, and rmdir
for directories.
If the removed name was the last link to a file and no processes have the file open
the file is deleted and the space it was using is made available for reuse.
If the name was the last link to a file but any processes still have the file open
the file will remain in existence until the last file descriptor referring to it is
closed.
If the name referred to a symbolic link the link is removed.
If the name referred to a socket, fifo or device the name for it is removed but
processes which have the object open may continue to use it.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropri
ately.
ERRORS
EFAULT pathname points outside your accessible address space.
EACCES Write access to the directory containing pathname is not allowed for the
process's effective uid, or one of the directories in pathname did not allow
search (execute) permission.
EACCES Write access to the directory containing pathname is not allowed for the
process's effective uid, or one of the directories in pathname did not allow
search (execute) permission.
EPERM The directory containing pathname has the sticky-bit (S_ISVTX) set and the
process's effective uid is neither the uid of the file to be deleted nor
that of the directory containing it.
ENAMETOOLONG
pathname was too long.
ENOENT A directory component in pathname does not exist or is a dangling symbolic
link.
ENOTDIR
A component used as a directory in pathname is not, in fact, a directory.
ENOMEM Insufficient kernel memory was available.
EROFS pathname refers to a file on a read-only filesystem.
CONFORMING TO
ANSI C, SVID, AT&T, POSIX, X/OPEN, BSD 4.3
BUGS
Infelicities in the protocol underlying NFS can cause the unexpected disappearance
of files which are still being used.
NOTE
Under libc4 and libc5, remove was an alias for unlink (and hence would not remove
directories).
SEE ALSO
unlink(2), rename(2), open(2), rmdir(2), mknod(2), mkfifo(3), link(2), rm(1),
unlink(8)
Bilden sie ein Team von 3 Mitgliedern
Erstellung Sie gemeinsam einen Texte mit Namen und Matr.Nr. der AutorenInnen. Abgabe einer Kopie des Textes an den Dozenten vor Beginn der Vorlesung am Di (1 Woche nach Aufgabenstellung). Falls die Aufgabe ausführbaren Programmcode enthält wäre die zusätzliche Übergabe des Quelltextes auf Diskette oder per email wünschenswert, aber nicht verbindlich. Im Falle von Programmcode muss im Programmtext auch nochmals Name und Matr.Nr. erscheinen.
Präsentation der Lösung als Team vor der gesamten Gruppe. Präsentationszeit (abhängig von der Gesamtzahl der Teams) 3-5 Min. Mögliche Punkte: 1-2 im Normalfall. Bei besonders guten Leistungen bis zu 3 Punkten.
Versuchen Sie in dem Text Antworten auf folgende Aufgaben zu formulieren:
Das Thema Sicherheit ist heutzutage sehr wichtig. Ein Teilbereich in diesem Thema sind z.B. 'sichere' Passwörter. Es soll ein einfaches Programm geschrieben werden, das demonstrieren soll, wie leicht bzw. wie schwer es ist, ein Passwort zu knacken. Realisieren Sie folgenden experimentellen Aufbau:
Legen sie eine Textdatei an, in der sie eine Reihe von Passwörter hineinschreiben, getrennt durch SPACE (=Leerzeichen, ASCII-Kode dezimal 32). Benutzen sie nur Kleinbuchstaben 'a,b, ..., z'. Beginnen sie mit der Länge 2, und steigern Sie die Länge bis zu einer Zahl, die Ihren Computer eine von Ihnen festgelegte maximale Zeit rechnen lässt.
Das Programm selbst soll folgende Aufgaben erfüllen:
Sie lesen das nächste Wort w aus Ihrer Testdatei mit den Passwörtern
Mit dem Zufallsgenerator rand() erzeugen Sie ein hypothetisches Wort w' von der gleichen Länge wie das Testwort w
Falls (w' == w) WAHR, dann schreiben Sie die Anzahl der Versuche, die der Zufallsgenerator benötigt hat, um w zu 'erkennen', in eine Ergabnisdatei mit folgendem Format: TESTWORT : BENÖTIGTE ANZAHL VON VERSUCHEN;
Falls (w' == w) FALSCH, dann erzeugen Sie ein neues hypothetisches Wort w' von der gleichen Länge wie das Testwort w und prüfen auf Erfolg.
Wenn sie alle Testworte aus Ihrer Datei abgearbeitet haben bzw. bis Ihr Computer die maximale Anzahl von Durchgängen erreicht hat, die Sie zulassen wollen, dann geben Sie die Ergebnisdatei mit allen Ergebissen auf dem Bildschirm aus.