|
Beispiel: Programm mit wahlfreiem Zugriff auf eine Datei
#include <stdio.h>
int main(void)
{
long pos;
int count;
FILE *fp;
int mode = 0;
char c;
fp = fopen("daten.bin","w+");
if (fp == NULL)
{
printf("Fehler beim Oeffnen der Datei\n");
exit(1);
}
/* Datei beschreiben */
fputs("abcdefghijklmnopqrstuvwxyz",fp);
puts("abcdefghijklmnopqrstuvwxyz");
printf("\n");
/* Wahlfreier Zugriff auf Datei */
printf("Eingabe der Positeon im File (0 bis 25):\n");
scanf("%ld",&pos);
fseek(fp,pos,mode);
pos = ftell(fp);
printf("Dateipositeon ist %ld\n",pos);
fread(&c,1,1,fp);
printf("\nBuchstabe an dieser Positeon: %c\n\n",c);
fclose(fp);
return 0;
}
Beispiel: Hexdump
Der Inhalt einer Datei soll Hexadezimal und in ASCII ausgegeben werden.
Für die Bildschirmausgabe soll das Programm die Datei blockweise anzeigen,
jeweils 16 Zeilen. Der folgende Bildschirmabzug zeigt die Ausgabe:
Adresse 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
00000000 : 2F 2A 20 48 65 78 64 75 6D 70 20 65 69 6E 65 72 /* Hexdump einer
00000010 : 20 44 61 74 65 69 20 2A 2F 0D 0A 0D 0A 23 69 6E Datei */....#in
00000020 : 63 6C 75 64 65 20 3C 73 74 64 69 6F 2E 68 3E 0D clude <stdio.h>.
00000030 : 0A 23 69 6E 63 6C 75 64 65 20 3C 73 74 64 6C 69 .#include <stdli
00000040 : 62 2E 68 3E 0D 0A 0D 0A 23 64 65 66 69 6E 65 20 b.h>....#define
00000050 : 52 45 54 20 31 33 20 20 20 20 20 20 20 20 20 20 RET 13
00000060 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 2F /
00000070 : 2A 20 52 65 74 75 72 6E 2D 54 61 73 74 65 20 2A * Return-Taste *
00000080 : 2F 0D 0A 23 64 65 66 69 6E 65 20 42 45 45 50 20 /..#define BEEP
00000090 : 70 75 74 63 68 61 72 28 27 5C 30 37 27 29 20 20 putchar('\07')
000000A0 : 20 20 20 20 20 20 20 20 20 20 2F 2A 20 53 69 67 /* Sig
000000B0 : 6E 61 6C 74 6F 6E 20 61 75 73 67 65 62 65 6E 20 nalton ausgeben
000000C0 : 2A 2F 0D 0A 0D 0A 0D 0A 2F 2A 20 67 6C 6F 62 61 */....* globa
000000D0 : 6C 65 20 56 61 72 69 61 62 6C 65 20 2A 2F 0D 0A le Variable */..
000000E0 : 46 49 4C 45 20 2A 65 69 6E 3B 20 20 20 20 20 20 FILE *ein;
000000F0 : 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
Adresse 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
Anmerkungen zum Programm:
- Da immer Blöcke von 16 Zeilen zu je 16 Zeichen dargestellt werden und in
jeder Zeile zweimal auf die Daten zugegriffen wird, ist es sinnvoll, zumindest
eine Zeile komplett in einen Puffer (Feld) einzulesen. Weil seitenweise geblättert
werden soll, ist es sogar ratsam, eine komplette Bildschirmseite (16*16 = 256
Bytes) auf einmal von der Datei in den Puffer zu lesen und dann darzustellen.
- Da es unwahrscheinlich ist, daß eine Datei genau ein Vielfaches von 256
Bytes lang ist, muß am Dateiende der restliche Puffer mit einem Wert gefüllt werden,
der anzeigt, daß die Daten nicht mehr zur Datei gehören. Vorschlag: Wert der
Datenbytes = 0 bis 255, Füller = -1). Die Datei muß natürlich Byte für Byte gelesen
werden.
- Da vorwärts und rückwärts geblättert werden soll, muß wahlfrei auf die Datei
zugegriffen werden. Dazu verwendet man eine Long-Variable, die die aktuelle
Lesepositeon (erstes zu lesendes Byte) speichert und die dann um 256 incrementiert
oder decrementiert wird. Beim vor- und zurückblättern muß man natürlich auch
auf Dateianfang oder -ende testen(feof()). Das Positeonieren innerhalb
der Datei erfolgt mit der Funktion fseek().
- Hexzahlen sollen mit führenden Nullen ausgeben werden. Bei der ASCII-Darstellung
sollen Zeichen mit den Codes 0 bis 31 als Punkt dargestellt werden.
Das Programm sieht dann so aus (aus Gründen der Übersichtlichkeit wurde auf ungepuffertes
Einlesen verzichtet).
#include <stdio.h>
#include <stdlib.h>
#define RET 13 /* Return-Taste */
#define BEEP putchar('\07') /* Signalton ausgeben */
/* globale Variable */
FILE *ein; /* Eingabedatei */
char name[64]; /* Dateiname */
int ende = 0; /* Dateiende erreicht? */
long positeon; /* aktuelle Positeon in 'ein' */
int puffer[16][16]; /* Puffer fuer eine Seite */
/* Funktions-Deklarationen */
void seitelesen(long positeon); /* Puffer aus Datei lesen */
void ausgabe(long positeon); /* Puffer darstellen */
/* Hauptprogramm */
int main(int argc, char *argv[])
{
int command; /* Bediener-Kommando */
if (argc < 2) /* Datei ueber Kommandozeile? */
{
printf("Dateiname: "); /* Dann ueber Tastatur */
scanf("%s",&name);
}
else
strcpy(name,argv[1]);
ein = fopen(name,"rb"); /* Eingabe eroeffnen */
if (ein == NULL)
{
printf("Eingabedatei kann nicht eroeffnet werden\n");
exit(1);
}
positeon = 0; /* Dateianfang */
for(;;) /* endlose */
{ /* Hauptschleife */
seitelesen(positeon);
ausgabe(positeon);
command = getchar(); /* Befehlstaste lesen */
switch (command)
{
case '+' : if (feof(ein) == 0) /* naechster Block */
positeon = positeon + 256;
else BEEP;
break;
case 'b' : /* vorhergehender Block */
case 'B' :
case '-' : if (positeon >= 256)
positeon = positeon - 256;
else BEEP;
break;
case 'Q' : /* Beenden */
case 'q' : fclose(ein); exit(0);
break;
default : BEEP; /* alle anderen Tasten */
} /* end switch */
} /* end for */
return 0;
}
/* Funktionsdefinitionen */
void seitelesen(long positeon) /* Puffer aus Datei lesen */
{
int i, j; /* Feldindexe */
int zeichen; /* gelesendes Zeichen */
fseek(ein,positeon,SEEK_SET); /* Pos. ab Dateianfang */
i = j = 0;
do
{ /* zeichenweise einlesen */
zeichen = getc(ein);
puffer[i][j] = zeichen;
j++;
if (j == 16) (i++, j = 0);
} /* bis Puffer voll oder EOF */
while (i*16+j < 256 && zeichen != EOF);
while (i*16+j < 256) /* Rest-Puffer auffuellen */
{
puffer[i][j] = -1;
j++;
if (j == 16) (i++,j = 0);
}
}
void ausgabe(long positeon) /* Puffer darstellen */
{
int i, j; /* Feldindexe */
printf("Dump von *** %s *** \n",name);
printf("\n");
printf("Adresse 0 1 2 3 4 5 6 7 8 9 A B C D E F");
printf(" 0123456789ABCDEF\n");
printf("\n");
for (i = 0; i < 16; i++) /* 16 Zeilen */
{
printf("%08lX : ",positeon);
for (j = 0; j < 16; j++) /* Inhalt hexadezimal */
if (puffer[i][j] < 0)
printf(" ");
else
printf(" %02X",puffer[i][j]);
printf(" ");
for (j = 0; j < 16; j++) /* Inhalt als ASCII-Zeichen */
if (puffer[i][j] > 31 && puffer[i][j] != 127)
printf("%c",puffer[i][j]);
else
if (puffer[i][j] < 0) /* Datei zuende - Blanks */
printf(" ");
else
printf("."); /* nicht druckbares Zeichen */
printf("\n");
positeon = positeon + 16;
}
printf("\n");
printf("Adresse 0 1 2 3 4 5 6 7 8 9 A B C D E F");
printf(" 0123456789ABCDEF\n");
printf("\n");
printf("Weiter mit <+> Zurueck mit <B>/<->");
printf(" Abbruch mit <Q>\n");
fflush(stdout);
}
|
|
|