Enrere Mòdul 8
Fonaments de Programació. Llenguatge C/C++---
Pràctica    Resum teòric Exercicis
Pràctica d'ampliació

 
Dump

En aquesta pràctica veurem una interessant aplicació de les funcions fseek() i fread()

 

Desenvolupament de la pràctica

Aquest interessant exemple fa ús de la funció fseek() per poder examinar el contingut d'un arxiu en un doble format: codi ASCII i en hexagesimal. Es podrà veure el contingut de l'arxiu en sectors de 128 octets. L'estil de sortida serà semblant al del comandament DOS Debug amb l'opció D.

Creeu un nou arxiu del tipus C anomenat m8p09.c i escriviu el següent codi:

//m8p09.c - DUMP -

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define MIDA 128

unsigned char buf[MIDA];
void mostrar(int);

int main (int argc, char *argv[]){
    FILE *fp;
    int sector, n;
    if (argc!=2){
        printf("nombre de paràmetres incorrecte\n");
        exit(1);
    }

    if((fp=fopen(argv[1], "rb"))==NULL){ 
        printf("no es pot obrir l'arxiu\n");
        exit(1);
    }

    do{
        printf("introduïu el sector: ");
        scanf("%d", &sector);
        if(fseek(fp, sector*MIDA, SEEK_SET)){ 
            printf("error de fseek\n");
        }
        if((n=fread(buf, 1, MIDA, fp)) !=MIDA){
            printf("trobat EOF\n");
        }

        mostrar(n);
    }while(sector>=0);

    return 0;
}

void mostrar(int n){
   int i,j;
   for(i=0;i<n/16; i++){
     for(j=0;j<16;j++) printf("%3X", buf[i*16+j]);printf(" ");
     for(j=0;j<16;j++) {
        if (isprint(buf[i*16+j])) printf("%c", buf[i*16+j]);
        else printf(".");
     }
     printf("\n");
   }
}

Captura de l'execució del programa.

 

Explicació del programa

L'execució aquest programa necessita un argument que es passa a través de la funció main(). El programa comprova que s'ha introduït aquest argument i, en cas contrari, informa de l'error i acaba l'execució:

 
    if (argc!=2){
        printf("nombre de paràmetres incorrecte\n");
        exit(1);
    }

S'obre l'arxiu especificat en mode de lectura i binari (rb) i demana a l'usuari la introducció d'un sector. La cerca d'aquest sector en l'arxiu es fa amb la funció fseek():

 
        if(fseek(fp, sector*MIDA, SEEK_SET)){ 
            printf("error de fseek\n");
        }

En aquest cas, situa el punter o marcador de l'arxiu a la posició sector*MIDA, des del començament (SEEK_SET). Si sector=0 se situa el punter al començament de l'arxiu. Si sector=1 se situa el punter a la posició 128, i així successivament. Si es produeix un error, degut segurament a que es sobrepassa la mida de l'arxiu la funció fseek() torna 0 i, per tant, es pot fer servir aquest valor de retorn en una comprovació. 

Una vegada situat el punter de l'arxiu a la posició correcta, es fa una lectura dels 128 octets amb la funció fread():

 
       if((n=fread(buf, 1, MIDA, fp)) !=MIDA){
            printf("trobat EOF\n");
        }

En aquest cas llegeix de la posició actual de l'arxiu apuntat per fp 1 bloc de MIDA (=128) octets i els posa a la posició apuntada pel punter buf. La funció fread() retorna el nombre real d'octets llegits. En el cas que el valor de retorn no coincideix amb MIDA vol dir que s'ha trobat abans el final de l'arxiu. 

Per visualitzar el contingut d'aquest sector es fa servir la funció mostrar(). Aquesta funció fa paquets de 16 octets i el representa cada paquet en una línia, primer en format hexagesimal printf("%3X", buf[i*16+j]);printf(" ");

i després en format ASCII:

 
        if (isprint(buf[i*16+j])) printf("%c", buf[i*16+j]);
        else printf(".");

En aquest últim cas, primer comprova si el caràcter és imprimible amb la funció imprint(), en cas afirmatiu escriu l'octet com a caràcter i en cas negatiu com un punt. La sortida aconseguida és com aquesta:

 
 9A  B  0  0  0  0  0  0  0  0  0  0  0  0  0  0  ................
 40 10 30 40 2E 64 65 62 75 67 24 53  0  0  0  0  @.0@.debug$S....
  0  0  0  0 7B  0  0  0 9E  B  0  0 19  C  0  0  ....{...........
  0  0  0  0  2  0  0  0 48 10 10 42 2E 64 65 62  ........H..B.deb
 75 67 24 54  0  0  0  0  0  0  0  0 3C  0  0  0  ug$T........<...
 2D  C  0  0  0  0  0  0  0  0  0  0  0  0  0  0  -...............
 48  0 10 42 2D 64 65 66 61 75 6C 74 6C 69 62 3A  H..B-defaultlib:
 4C 49 42 43 44 20 2D 64 65 66 61 75 6C 74 6C 69 LIBCD -defaultli