Jump to content
José Ol'Ivar

Manipulação de arquivos

Recommended Posts

José Ol'Ivar

Problema aparentemente bem simplório: Código que insere registro em aquivo ordenado, mantendo a ordenação e sem uso de arquivo auxiliar.

Entretanto, perdi a tarde toda hoje tentando descobrir por que o código abaixo não funciona:

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
    
 main()
 {  
    typedef struct 
    {
       char Mat[12]; char Nome[40];
    } REGISTRO;
     
    const unsigned int TAM_REG = sizeof(REGISTRO);
     
    char NomeArq[100];
    FILE* fp;
    REGISTRO Reg, RegAux;
    unsigned long int tam_arq, pos;
    unsigned int inicio, mediana, fim;
     
    printf("\nDigite o nome do arquivo a abrir: "); fflush(stdin); gets(NomeArq);
    
    if((fp = fopen(NomeArq, "r+b")) == NULL)
    {
       printf("\nImpossivel acessar o arquivo");
       exit(1);
    }
    
    printf("\nDigite o registro a incluir: \n");
    printf("\nMatricula: "); fflush(stdin); scanf("%s", Reg.Mat); 
    printf("Nome: "); fflush(stdin); gets(Reg.Nome); 
      
        
    /*Compara-se cada um dos registros do arquivo, até encontrar um com matrícula maior que a do registro a inserir*/
	
	while(fread(&RegAux, TAM_REG, 1, fp))    
	   if(atoi(RegAux.Mat) > atoi(Reg.Mat))
	   {
	                                                        
	      fseek(fp, (long) -TAM_REG, SEEK_CUR); fwrite(&Reg, TAM_REG, 1, fp); 
		  Reg = RegAux;	
	   } 
	                             
    fwrite(&Reg, TAM_REG, 1, fp);   
	               
    close(fp); printf("\n\nFIM DO PROGRAMA"); getchar();
 }  

Acabei por descobrir que o defeito está no ponteiro de leitura e escrita em arquivo. Ao que parece, efetuar o "fwrite" e depois do "fread" faz o ponteiro saltar anormalmente, para trás.

O código abaixo resolve o problema, ao se fazer o posicionamento cogente do ponteiro:

 #include <stdio.h>
 #include <conio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
    
 main()
 {  
    typedef struct 
    {
       char Mat[12]; char Nome[40];
    } REGISTRO;
     
    const unsigned int TAM_REG = sizeof(REGISTRO);
     
    char NomeArq[100];
    FILE* fp;
    REGISTRO Reg, RegAux;
    unsigned long int tam_arq, pos;
    unsigned int inicio, mediana, fim;
     
    printf("\nDigite o nome do arquivo a abrir: "); fflush(stdin); gets(NomeArq);
    
    if((fp = fopen(NomeArq, "r+b")) == NULL)
    {
       printf("\nImpossivel acessar o arquivo");
       exit(1);
    }
    
    printf("\nDigite o registro a incluir: \n");
    printf("\nMatricula: "); fflush(stdin); scanf("%s", Reg.Mat); 
    printf("Nome: "); fflush(stdin); gets(Reg.Nome); 
      
        
    /*Usar-se-á método asssemelhado à pesquisa binária para posicionar o registro no contexto ordenado do arquivo*/
	
	/*Identificam-se os dados necessários à pesquisa binária*/
	
	fseek(fp, 0, SEEK_END); tam_arq = ftell(fp);  
     
    fim = tam_arq/TAM_REG; mediana = fim/2; inicio = 1;      
             
    /*Passa-se agora à pesquisa propriamente dita*/
    
    while(fim >= inicio)     
    {  
	   pos = (mediana-1)*TAM_REG;     /*'pos' aqui posicionará a leitura no meio do arquivo*/
	      
       fseek(fp, pos, SEEK_SET); fread(&RegAux, TAM_REG, 1, fp); 
                
       if(atoi(RegAux.Mat) < atoi(Reg.Mat))   
       {
          inicio = mediana + 1;
          mediana = (fim + inicio)/2;
       }
       else
       {
          fim = mediana - 1;
          mediana = (fim + inicio)/2;           
       } 
    }   
                                            
     
    /*Passa-se agora a incluir o registro na ordenação*/  
        
           
    if(atoi(RegAux.Mat) > atoi(Reg.Mat))
    {    	         
       do  
       { 
          pos = ftell(fp);
          
          fseek(fp, -TAM_REG, SEEK_CUR); fwrite(&Reg, TAM_REG, 1, fp);
              
          Reg = RegAux; 
		  
		  fseek(fp, pos, SEEK_SET);
       }  
       while(fread(&RegAux, TAM_REG, 1, fp));
         
       fwrite(&Reg, TAM_REG, 1, fp);
    }     
    else 
    {   
       while(fread(&RegAux, TAM_REG, 1, fp)) 
       {
       	  pos = ftell(fp);
       	  
          fseek(fp, -TAM_REG, SEEK_CUR); fwrite(&Reg, TAM_REG, 1, fp);
              
          Reg = RegAux; 
          
          fseek(fp, pos, SEEK_SET);
       }
       
       fwrite(&Reg, TAM_REG, 1, fp); 
    }
          
          
    close(fp); printf("\n\nFIM DO PROGRAMA"); getchar();
 }  

Alguém saberia me dizer qual a causa disso?

Share this post


Link to post
Share on other sites
HappyHippyHippo

a causa é tu não perceberes que quando fazes uma escrita no ficheiro (stream), tu não estás a injectar bits no meio do que já existe. o que estás a fazer é escrever sobre os bits que já lá se encontram.

nem me dei ao trabalho de analisar o segundo código (parece demasiado convoluto), mas se dizes que funciona, parabéns.


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
José Ol'Ivar

Tenho completa ciência do que diz, sim. Observe que não foi à toa que introduzi os comandos "fseek(fp, (long) -TAM_REG, SEEK_CUR);" e "Reg = ReaAux" dentro do condicional.

Sobre o caráter convoluto do segundo código, bem, respeito sua opinião, mas, tendo no horizonte o uso de pesquisa binária, não sei se teria como desdobrá-lo, rsrsrs.

Mas agradeço a atenção.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.