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

 
Dividir un arxiu en dues parts iguals i tornar a ajuntar-lo

En aquesta pràctica veurem una útil aplicació de la manipulació d'arxius binaris. Consisteix en la divisió d'un arxiu en dos parts iguals i, després, tornar a ajuntar-lo.

 

Desenvolupament de la pràctica

Moltes vegades ha passat que ens hem baixat un arxiu d'Internet i volem passar-lo a un disc de 3'' 1/4 i no hi cap. Els disquetes poden emmagatzemar un màxim d'1.4 MBytes. Les senzilles aplicacions que es mostren a continuació poden servir per a solucionar aquest problema. Consisteixen en dos programes, el primer dels quals permet dividir un arxiu en dos arxius de mida igual a la meitat de l'arxiu original. El segon dels programes permet construir l'arxiu original a partir de les dues meitats fetes abans.

Creeu un nou arxiu del tipus C++ anomenat m8p061.cc i escriviu el següent codi:

//m8p061.cc - Dividir un fitxer en dos parts iguals -

#include <stdio.h>

int mida(char *arxiu);

int main(int argc, char *argv[]){

    FILE *origen, *desti;
    int mid;
    char car;

    mid=mida(argv[1])/2;
    if((origen=fopen(argv[1],"rb"))==NULL){
         printf("error a l'obrir l'arxiu\n");
         return;
    }

    if((desti=fopen("arxiu1.dat","wb"))==NULL){
         printf("error a l'obrir l'arxiu\n");
         return;
    }


    car=getc(origen);
    while(mid--){
        putc(car,desti);
        car=getc(origen);
    }

    fclose(desti);

    if((desti=fopen("arxiu2.dat","ab"))==NULL){
         printf("error a l'obrir l'arxiu\n");
         return;
    }

    while(!feof(origen)){
         putc(car,desti);
         car=getc(origen);
    }

    fclose(desti);
    fclose(origen);

    return 0;



int mida(char *arxiu){
    FILE *f;


    if ((f=fopen(arxiu,"rb"))==NULL){
          printf("error, no s'ha pogut obrir l'arxiu\n");
          return 0; 
    }
    fseek(f, 0,SEEK_END);
    return ftell(f);

}

Explicació del programa

El programa anterior conté, a part de la funció principal, la funció mida() vista a la pràctica anterior. Recordem que aquesta funció torna el nombre total d'octets de l'arxiu que se li passa com argument.

A la funció main() se li passa com argument un paràmetre que és el nom de l'arxiu que volem dividir en dos. Es calcula la mida d'aquest arxiu i la seva meitat. En el cas que el nombre total d'octets no sigui un nombre parell, com que la divisió es fa entre nombres enters, el resultat d'aquesta divisió és l'aproximació per defecte de la divisió (ex: Si mida=13, la mid serà 6).

La primera part de l'extracció i escriptura de dades es fa amb la següent part de codi:

car=getc(origen);
    while(mid--){
        putc(car,desti);
        car=getc(origen);
    }

Aquest bucle s'executa mid cops, després dels quals es tanca l'arxiu de destí i es torna a obrir un altre arxiu de destí.

La segona part de l'extracció i escriptura es fa amb la següent part de codi:

    while(!feof(origen)){
         putc(car,desti);
         car=getc(origen);
    }

En aquest cas, el bucle s'executa fins que troba el final de l'arxiu origen. En els arxius binaris no és convenient fer servir la constant EOF, ja que aquesta constant és igual a -1, valor que es pot trobar en un arxiu que no sigui de text sense que signifiqui que s'ha arribat al final de l'arxiu.

La segona part d'aquesta pràctica ha de ser, sens dubte el procés contrari, és a dir, tornar a ajuntar les dues parts. Per aquesta tasca farem servir el següent programa:

Creeu un nou arxiu del tipus C++ anomenat m8p062.cc i escriviu el següent codi:

//m8p062.cc - Ajuntar dos arxius en un de sol -

#include <stdio.h>


int main(int argc, char *argv[]){

   FILE *origen, *desti;
   char car;


   if((origen=fopen(argv[1],"rb"))==NULL){
      printf("error a l'obrir l'arxiu %s\n",argv[1]);
      return 0;
   }

   if((desti=fopen(argv[3],"wb"))==NULL){
      printf("error a l'obrir l'arxiu% s\n",argv[3]);
      return 0;
   }


   car=getc(origen);
   while(!feof(origen)){
      putc(car,desti);
      car=getc(origen);
   }

   fclose(origen);

   if((origen=fopen(argv[2],"rb"))==NULL){
      printf("error a l'obrir l'arxiu %s\n",argv[2]);
   return 0;
   }

   while(!feof(origen)){
      putc(car,desti);
      car=getc(origen);
   }

   fclose(desti);
   fclose(origen);
   return 0;
}

 

 

Explicació del programa

El primer programa d'aquesta pràctica ha triat arbitràriament que el nom dels arxius creats són arxiu1.dat i arxiu2.dat. Aquests noms es poden modificar o, millor encara, demanar-los per tal d'entrar-los per teclat. El programa que fa la unió ja preveu aquesta circumstància i, per tant, s'ha d'incloure tres arguments en el moment de l'execució. El primer i segon arguments són els noms dels arxius origen i, el tercer argument és el nom de l'arxiu destí que contindrà la suma dels altres dos. Per exemple, es podria executar escrivint:

El funcionament d'aquest segon programa és molt senzilla, només s'escriu des del primer arxiu origen a l'arxiu destí fins que s'arribi al final de l'arxiu origen i, després, es tanca aquest arxiu origen i es torna a obrir l'altre arxiu origen. S'escriu, a continuació, el contingut d'aquest nou arxiu origen a l'arxiu destí fins que troba de nou el final de l'arxiu origen.