MANIPULAÇÃO DE DADOS EM ARQUIVO BINÁRIO

 

Caso seja necessário criar um programa que grave, altere ou exclua dados dos frequentadores de uma academia, nesse tutorial vamos ver passo a passo como criar um código eficiente para isso, desde a criação de uma struct, até a exclusão de um frequentador por completo.

 

Criando e inserindo dados de uma struct em um arquivo:

 

A primeira coisa a fazer é entender o problema, neste tutorial vamos usar como referência os dados dos frequentadores de uma academia, que são: cpf, nome, peso, sexo e data de inscrição, depois disso, crie uma struct, veja um exemplo:

 
#include <stdio.h>
#include <conio.h>
#define MAX_CPF 12
#define MAX_NOME 60
// Inicio da criação da Estrutura:
typedef struct
{
   char cpf[MAX_CPF];
   char nome[MAX_NOME];
   float peso;
   char sexo;
   int dia,mes,ano; // data de inscrição.
}tipoFrequentador; // Criando um tipo de dado da estrutura:
 

Note que depois da criação da struct é criado um tipo de dado dela, esse tipo será bastante usado na manipulação de dados em arquivo, por isso é sempre importante criar um para cada struct que você declarar.

 

Agora que você tem o tipo da estrutura criado, é possivel declarar uma variável usando o novo tipo, exemplo:

 
//...
// Declaracoes
      tipoFrequentador cliente; 
//...
 

O próximo passo será efetuar a leitura dos dados, exemplo: (Como é um exemplo nenhuma leitura está sendo validada, porém não se esqueça de validar todos os dados!) :

 
//...
int main(void)
{
// Declaracoes
  tipoFrequentador cliente;
// Instrucoes
  puts("Digite o CPF do frequentador:");
  scanf("%s",cliente.cpf);   // Lendo o CPF
  puts("Digite o Nome do frequentador:");
  scanf("%s",cliente.nome); // Lendo o Nome completo
  fflush(stdin);
  puts("Digite o Peso do frequentador:");
  scanf("%f",&cliente.peso);   // Lendo o Peso
  fflush(stdin);
  puts("Digite o Sexo do frequentador:");
  scanf("%c",&cliente.sexo);   // Lendo o Sexo (M ou F)
  puts("Digite o Dia de inscricao do frequentador:");
  scanf("%d",&cliente.dia);   // Lendo o dia
  puts("Digite o Mes de inscricao do frequentador:");
  scanf("%d",&cliente.mes);   // Lendo o mês
  puts("Digite o Ano de inscricao do frequentador:");
  scanf("%d",&cliente.ano);    // Lendo o ano
  getch();
  return 0;
}
//...
 

Criando um arquivo:

 

Após a leitura dos dados, já é possível gravar essa struct em arquivo, mas primeiro é preciso criar esse arquivo! O primeiro passo é declarar um arquivo, para isso há até um tipo específico que é o "FILE", veja o exemplo:

 
//...
// Declaracoes
      FILE *arqFrequentadores;   //Declaração de um arquivo
      tipoFrequentador cliente
//...
 

Note que a variável é na verdade um ponteiro, só que do tipo FILE, ou seja, ela vai armazenar o endereço de seu arquivo. Observe que seu arquivo ainda não foi criado, apenas a variável que vai armazenar o endereço dele é que foi decladara!

 

Para seu arquivo passar a existir, você precisa abrí-lo, mas antes você precisa pensar em um nome para ele, como neste caso estamos usando uma estrutura para frequentadores de uma academia, um nome ideal seria "dadosFrequentadores.bin", note que a extensão não será necessariamente ".bin", podendo ficar à escolha do programador! Após pensar no nome de seu arquivo, crie um "define" com o nome nome dele:

 
//...
#define ARQFREQUENT "dadosFrequentadores.bin"
//...
 

Isso vai facilitar bastante o trabalho do programador, pois caso ele queira mudar a extensão ou o nome do arquivo, tudo será feito em apenas uma linha. No exemplo acima está sendo usado "ARQFREQUENT", mas não hesite em usar outros nomes que você não esqueça! (tudo em maiúsculo!).

 

Agora que você sabe o nome do arquivo, já é possivel abrí-lo, sempre é aconselhável abrir os arquivos apenas quando necessário, e feito isso, fechá-lo imediatamente! Ou seja, vamos abrí-lo apenas na hora de gravar os dados nele! O próximo passo é criar uma função que grave os dados dessa struct no arquivo, essa função vai receber como parâmetro o endereço de sua struct. Veja o exemplo:

 
//...
// Subprograma 1
//  Objetivo  : Gravar uma estrutura de dados em um arquivo bínario.
//  Parâmetro : Struct.
//  Retorno   : Nenhum.
void gravaDados(tipoFrequentador *estrutura) 
// O parâmetro é um ponteiro que vai receber o endereço da estrutura!
{
   FILE *arq;     
   // Declarando um ponteiro de arquivo.                                                    
   if (!(arq = fopen(ARQFREQUENT,"a+b")))   
   // Abrindo o arquivo(caso não tenha sucesso, será executado o "exit(1)"
      exit(1);
   fwrite(estrutura,sizeof(tipoFrequentador),1,arq); 
   // Gravando a estrutura completa no arquivo!
   fclose(arq);        
   // fechando o arquivo imediatamente.                                               
}  
//... Não se esqueça de criar o protótipo da função!
 

No exemplo acima, como usamos o modo "a+b" de abertura, se o arquivo não existir ele será criado, e se existir será atualizado (será aberto com o apontador no final do arquivo), para arquivos não-binários use "a+t". Para chamar essa função que acabamos de criar, mande como parâmetro o endereço da struct que você acabou de ler, exemplo:

 
//...
   gravaDados(&cliente);
//...
 

Feito isso, você terminou a gravação dos dados, você vai encontrar esse arquivo na mesma pasta em que seu código fonte está salvo! Você pode até abrí-lo com o bloco de notas, mas como a gravação foi binária você não vai entender o que foi escrito, apenas o computador! Veja o código fonte do exemplo completo:

 
/*
 Sintese
   Objetivo: Salvar uma estrutura de dados em um arquivo binário.
 
   Entrada : Cpf,nome,peso,sexo,data de inscrição.

   Saida   : Nenhuma.
*/

#include <stdio.h>
#include <conio.h>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
// Estruturas
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
} tipoFrequentador;
// Protótipos
void gravaDados(tipoFrequentador *estrutura);
// Instruções
int main(void)
{
// Declaracoes
  tipoFrequentador cliente; 
  FILE *arqFrequentadores; 
// Instrucoes
//  PRIMEIRO EFETUANDO A LEITURA DOS DADOS
  puts("Digite o CPF do frequentador:");
  scanf("%s",cliente.cpf);  
  puts("Digite o Nome do frequentador:");
  scanf("%s",cliente.nome); 
  fflush(stdin);
  puts("Digite o Peso do frequentador:");
  scanf("%f",&cliente.peso);          
  fflush(stdin);
  puts("Digite o Sexo do frequentador:");
  scanf("%c",&cliente.sexo);        
  puts("Digite o Dia de inscricao do frequentador:");
  scanf("%d",&cliente.dia);         
  puts("Digite o Mes de inscricao do frequentador:");
  scanf("%d",&cliente.mes);         
  puts("Digite o Ano de inscricao do frequentador:");
  scanf("%d",&cliente.ano);        
//   FIM DA LEITURA
  gravaDados(&cliente);         
  system("CLS");
  printf("Dados gravados!\n");
  getch();
  return 0;
}
// Subprograma 1
//   Objetivo  : Gravar uma estrutura de dados em um arquivo bínario.
//   Parâmetro : Struct.
//   Retorno   : Nenhum.
void gravaDados(tipoFrequentador *estrutura) 
{
  FILE *arq;                                                            
  if (!(arq = fopen(ARQFREQUENT,"a+b")))       
     exit(1);
  fwrite(estrutura,sizeof(tipoFrequentador),1,arq);  
  fclose(arq);                                                            
}
 

Observações importantes: O programa acima é apenas um exemplo, ele salva somente uma struct por vez! Para fazer um programa que leia diversos registros de clientes e os salve, você terá que mudar a lógica, de forma que após a gravação, seja permitido a gravação de mais clientes, lembre-se: não é necessária a criação de um vetor de struct, pois o próprio arquivo é um vetor. Use a mesma struct para ler os dados de todos os frequentadores!

 

Alterando dados em um arquivo

Para alterar dados em um arquivo, é preciso seguir alguns passos para o sucesso da operação, neste exemplo você vai alterar os dados de um frequentador da academia, de acordo com os seguintes passos:

 

-Pedir o CPF do frequentador a ser alterado.

-Localizar a struct com esse CPF.

-Pedir o que ele deseja alterar (o CPF não pode ser alterado).

-Ler o novo dado que o usuário informar.

-Chamar uma das funções de alteração de acordo com a escolha do usuário.

-Confirmar a alteração.

-Gravar o novo dado por cima do antigo.

-Fim.

 

Para a realização da alteração de dados em arquivo, é necessário ter um bom conhecimento da função fseek em conjunto com sizeof.

 

Veja um exemplo de como localizar uma struct no arquivo com o CPF que o usuário digitou:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
//Estruturas:
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
} tipoFrequentador ;
//Protótipos:
int localizaStructPorCpf(char *pCpfDigitado);

int main(void)
{
// Declaracoes
  int posicaoStruct;
  char cpfDigitado[MAX_CPF];
// Instrucoes
  printf("Digite o cpf do frequentador que deseja alterar:\n");
  scanf("%s",cpfDigitado);
  //Validar CPF!
  posicaoStruct = localizaStructPorCpf(cpfDigitado); 
  if (posicaoStruct == -1)
     printf("Nenhum Registro com esse CPF foi encontrado!\n");
  else
  {
      //Se entrar aqui, é porque achou o CPF!
      //Próximo passo: chamar as funções de alteração.
  } 
  getch();
  return 0;
}
// Subprograma 1
//  Objetivo  : Encontrar uma Struct com o mesmo CPF digitado.
//  Parâmetro : Cpf Digitado.
//  Retorno   : Posição da estrutura no arquivo.
int localizaStructPorCpf(char *pCpfDigitado)
{
  FILE *arq;
  int contBytes=0;
  tipoFrequentador estrutura;
  if (!(arq = fopen(ARQFREQUENT,"rb"))) // Abrindo com o modo 'apenas leitura'.
      exit(1);
  while(fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     contBytes=ftell(arq); 
     if (strcmp(estrutura.cpf,pCpfDigitado)==0)
     {
           fclose(arq); // sempre fechar arquivo
           return contBytes - sizeof(tipoFrequentador); 
     }                                                                                          
  }
  // se saiu o while, quer dizer que não achou nenhum cpf equivalente!
  fclose(arq); //sempre fechar arquivo
  return -1; 
}
 

Caso o usuário digite um CPF válido, a nova função retorna a posição do registro deste frequentador, caso contrário ela retorna -1, indicando que não existe frequentador com tal CPF. Agora que já temos o frequentador desejado, peça ao usuário qual dos dados ele deseja alterar, veja um exemplo:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
}tipoFrequentador;

int main(void)
{
// Declaracoes
  int opcao;
  tipoFrequentador novaEstrutura;
// Instrucoes
  do
  {
     printf("Digite o que você deseja alterar:\n\n");
     printf("1 - Nome\n");
     printf("2 - Peso\n");
     printf("3 - Sexo\n");
     printf("4 - Data de inscricao\n\n");
     scanf("%d",&opcao);
     if ((opcao < 1) || (opcao > 4))
        printf("opcao invalida! Digite novamente:\n");
  }while((opcao < 1) || (opcao > 4));
  switch(opcao)
  {
     case 1:
     {
         printf("\nDigite o novo nome:\n");
         scanf("%s",novaEstrutura.nome);
         //Validar nome.
         //Perguntar ao usuario se deseja mesmo alterar...
                    
         //Chamar a função de alterar nome.
         break;
     }
     case 2:
     {
           printf("\nDigite o novo peso:\n");
           scanf("%f",novaEstrutura.peso);
           //Validar peso.
           //Perguntar ao usuario se deseja mesmo peso...
                    
           //Chamar a função de alterar peso.
           break;
     }
     case 3:
     {
          printf("\nDigite o novo sexo:\n");
          scanf("%c",novaEstrutura.sexo);
          //Validar sexo.
          //Perguntar ao usuario se deseja mesmo sexo...
                   
          //Chamar a função de alterar sexo.
          break;
     }
     case 4:
     {
          puts("Digite o novo dia:");
          scanf("%d",&novaEstrutura.dia);         
          puts("Digite o novo mes:");
          scanf("%d",&novaEstrutura.mes);         
          puts("Digite o novo ano:");
          scanf("%d",&novaEstrutura.ano);  
          //Validar data
          //Perguntar ao usuario se deseja mesmo alterar data...
                    
          //Chamar a função de alterar data.
     }
  }
  getch();
  return 0;
}  
 

Agora que você já tem a posição do frequentador e o novo dado, é possivel ir para o último passo, a alteração de dados, que consiste basicamente em escrever a nova informação por cima da antiga. Neste exemplo, você vai criar uma função que altere o nome de um frequentador: Primeiramente observe o corpo da função de alterar nome:

 
// Subprograma 1
//  Objetivo  : Alterar o nome de um frequentador.
//  Parâmetro : Posição da struct e novo nome
//  Retorno   : Nenhum.
void alteraNomeFrequentador(int posicao, char *pNovoNome)
{
  FILE *arq;
  if (!(arq = fopen(ARQFREQUENT,"r+b"))) // Abrindo com o modo 'Leitura e escrita'.
     exit(1);//erro ao abrir o arquivo.
  fseek(arq,posicao,1); 
//Neste fseek estamos movendo o apontador do arquivo para a estrutura a ser alterada
  fseek(arq,MAX_CPF,1); 
//já neste estamos movendo o apontador para o inicio do nome do frequentador
//e como só o CPF vem antes do nome, temos que saltar o tamanho do CPF.
  fwrite(pNovoNome,MAX_NOME,1,arq);
  fclose(arq);
  printf("Nome modificado com sucesso!\n"); 
}
 

Agora observe o uso prático dela:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
} tipoFrequentador;

//Protótipos:
int localizaStructPorCpf(char *pCpfDigitado);
void alteraNomeFrequentador(int posicao, char *pNovoNome);

int main(void)
{
// Declaracoes
  int opcao;
  int posicaoStruct;
  char cpfDigitado[MAX_CPF];
  tipoFrequentador novaEstrutura;
// Instrucoes
  printf("Digite o cpf do frequentador que deseja alterar:\n");
  scanf("%s",cpfDigitado);
  //Validar CPF!
  posicaoStruct = localizaStructPorCpf(cpfDigitado); 
  if (posicaoStruct == -1)
     printf("Nenhum Registro com esse CPF foi encontrado!\n");
  else
  {
      do
      {
          printf("Digite o que você deseja alterar:\n\n");
          printf("1 - Nome\n");
          printf("2 - Peso\n");
          printf("3 - Sexo\n");
          printf("4 - Data de inscricao\n\n");
          scanf("%d",&opcao);
          if ((opcao < 1) || (opcao > 4))
            printf("opcao invalida! Digite novamente:\n");
     }while((opcao < 1) || (opcao > 4));
     switch(opcao)
     {
          case 1:
          {
              printf("\nDigite o novo nome:\n");
              scanf("%s",novaEstrutura.nome);
              //Validar nome.
              //Perguntar ao usuario se deseja mesmo alterar...
              alteraNomeFrequentador(posicaoStruct,novaEstrutura.nome);
                   
              break;
          }
          case 2:
          {
              printf("\nDigite o novo peso:\n");
              scanf("%f",&novaEstrutura.peso);
              //Validar peso.
              //Perguntar ao usuario se deseja mesmo alterar...
              
              //Chamar a função de alterar peso. 
              break;
          }
          case 3:
          {
              printf("\nDigite o novo sexo:\n");
              scanf("%c",&novaEstrutura.sexo);
              //Validar sexo.
              //Perguntar ao usuario se deseja mesmo sexo...
                   
              //Chamar a função de alterar sexo.
              break;
          }
          case 4:
          {
              puts("Digite o novo dia:");
              scanf("%d",&novaEstrutura.dia);         
              puts("Digite o novo mes:");
              scanf("%d",&novaEstrutura.mes);         
              puts("Digite o novo ano:");
              scanf("%d",&novaEstrutura.ano);  
              //Validar data
              //Perguntar ao usuario se deseja mesmo alterar data...
                
              //Chamar a função de alterar data.
          }
     }
  }
  getch();
  return 0;
}
// Subprograma 1
//  Objetivo  : Alterar o nome de um frequentador.
//  Parâmetro : Posição da struct e novo nome
//  Retorno   : Nenhum.
void alteraNomeFrequentador(int posicao, char *pNovoNome)
{
  FILE *arq;
  if (!(arq = fopen(ARQFREQUENT,"r+b"))) // Abrindo com o modo 'Leitura e escrita'.
    exit(1);//erro ao abrir o arquivo.
  fseek(arq,posicao,1); 
  fseek(arq,MAX_CPF,1);                       
  fwrite(pNovoNome,MAX_NOME,1,arq);
  fclose(arq);
  printf("Nome modificado com sucesso!\n"); 
}
// Subprograma 2
//  Objetivo  : Encontrar uma Struct com o mesmo CPF digitado.
//  Parâmetro : Cpf Digitado.
//  Retorno   : Posição da estrutura no arquivo.
int localizaStructPorCpf(char *pCpfDigitado)
{
  FILE *arq;
  int contBytes=0;
  tipoFrequentador estrutura;
  if (!(arq = fopen(ARQFREQUENT,"rb"))) // Abrindo com o modo 'apenas leitura'.
      exit(1);//erro ao abrir o arquivo.
  while(fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     contBytes=ftell(arq); 
     if (strcmp(estrutura.cpf,pCpfDigitado)==0)
     {
         fclose(arq); // sempre fechar arquivo       
         return contBytes - sizeof(tipoFrequentador); 
     }                                                  
  }
  // se saiu o while, quer dizer que não achou nenhum cpf equivalente!
  fclose(arq); // sempre fechar arquivo
  return -1; 
}
 

Feito isso, você concluiu a alteração de dados. O processo para alterar os outros dados do frequentador é o mesmo, a única coisa que muda é a posição do registro na memória.

 

Excluindo dados de um arquivo

 

Suponha que seja necessário deletar um frequentador da academia, para excluir uma struct do arquivo, você deve serguir os seguintes passos:

 

-Encontrar a struct a ser deletada.

-Criar um arquivo temporário.

-Copiar todos os registros para o arquivo temporário, menos o que será delatado.

-Deletar o arquivo de frequentadores original.

-Renomear o arquivo temporário com o mesmo nome do original.

-Fim.

 

Vejamos uma função que faz esse processo:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
#define ARQTEMP "frequentadorTemp.bin"

//...

// Subprograma 1
// Objetivo  : Deletar um Frequentador.
// Parâmetro : Apontador do frequentador.
// Retorno   : Nenhum.
void deletaFrequentador(int apontador)
{
//Declaraçoes
  FILE *arq,*arqTemp;
  tipoFrequentador estrutura;
  int contBytes=0;
//instruções:      
  if (!(arq = fopen(ARQFREQUENT,"rb"))) 
     exit(1);
  if (!(arqTemp = fopen(ARQTEMP,"wb"))) 
     exit(1);
  while(fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     if (contBytes == apontador) 
         fseek(arq,sizeof(tipoFrequentador),1);    
     else         
         fwrite(&estrutura,sizeof(tipoFrequentador),1,arqTemp); 
     contBytes = ftell(arq);//contador de bytes recebendo o apontador.
  }
  fclose(arq);
  fclose(arqTemp);
  remove(ARQFREQUENT); //Excluindo o arquivo de frequentadores original. 
  rename(ARQTEMP,ARQFREQUENT); 
  printf("Frequentador excluido com sucesso!\n");
  return;     
}
 

Note que a função recebe como parâmetro somente o apontador do registro, que será obtido pela mesma função que fez isso para alterar dados. Lembre-se! O comando remove só vai funcionar se nenhum arquivo estiver aberto! Agora veja o código completo, que altera ou exclui dados:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
#define ARQTEMP "frequentadorTemp.bin"
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
} tipoFrequentador;

//Protótipos:
int localizaStructPorCpf(char *pCpfDigitado);
void alteraNomeFrequentador(int posicao, char *pNovoNome);
void deletaFrequentador(int apontador);

int main(void)
{
// Declaracoes
  int opcao;
  int posicaoStruct;
  char cpfDigitado[MAX_CPF];
  tipoFrequentador novaEstrutura;
// Instrucoes
  printf("Digite o cpf do frequentador que deseja alterar:\n");
  scanf("%s",cpfDigitado);
  //Validar CPF!
  posicaoStruct = localizaStructPorCpf(cpfDigitado); 
  if (posicaoStruct == -1)
     printf("Nenhum Registro com esse CPF foi encontrado!\n");
  else
  {
    do
    {
       printf("Digite o que voce deseja alterar:\n\n");
       printf("1 - Nome\n");
       printf("2 - Peso\n");
       printf("3 - Sexo\n");
       printf("4 - Data de inscricao\n");
       printf("5 - DELETAR FREQUENTADOR\n\n");
       scanf("%d",&opcao);
       if ((opcao < 1) || (opcao > 5))
          printf("opcao invalida! Digite novamente:\n");
    }while((opcao < 1) || (opcao > 5));
    switch(opcao)
    {
        case 1:
        {
            printf("\nDigite o novo nome:\n");
            scanf("%s",novaEstrutura.nome);
            //Validar nome.
            //Perguntar ao usuario se deseja mesmo alterar...
            alteraNomeFrequentador(posicaoStruct,novaEstrutura.nome);
                 
            break;
        }
        case 2:
        {
            printf("\nDigite o novo peso:\n");
            scanf("%f",novaEstrutura.peso);
            //Validar peso.
            //Perguntar ao usuario se deseja mesmo alterar...
             
            //Chamar a função de alterar peso. 
            break;
        }
        case 3:
        {
            printf("\nDigite o novo sexo:\n");
            scanf("%c",novaEstrutura.sexo);
            //Validar sexo.
            //Perguntar ao usuario se deseja mesmo sexo...
                
            //Chamar a função de alterar sexo.
            break;
        }
        case 4:
        {
            puts("Digite o novo dia:");
            scanf("%d",&novaEstrutura.dia);         
            puts("Digite o novo mes:");
            scanf("%d",&novaEstrutura.mes);         
            puts("Digite o novo ano:");
            scanf("%d",&novaEstrutura.ano);  
            //Validar data
            //Perguntar ao usuario se deseja mesmo alterar data...
               
            //Chamar a função de alterar data.
            break;
        }
        case 5:// deletar frequentador.
        {
            deletaFrequentador(posicaoStruct);
         }
    }
  }
  getch();
  return 0;
}
// Subprograma 1
//  Objetivo  : Alterar o nome de um frequentador.
//  Parâmetro : Posição da struct e novo nome
//  Retorno   : Nenhum.
void alteraNomeFrequentador(int posicao, char *pNovoNome)
{
  FILE *arq;
  if (!(arq = fopen(ARQFREQUENT,"r+b"))) 
     exit(1);//erro ao abrir o arquivo.
  fseek(arq,posicao,1);
  fseek(arq,MAX_CPF,1);                            
  fwrite(pNovoNome,MAX_NOME,1,arq);
  fclose(arq);
  printf("Nome modificado com sucesso!\n"); 
}
// Subprograma 2
//  Objetivo  : Encontrar uma Struct com o mesmo CPF digitado.
//  Parâmetro : Cpf Digitado.
//  Retorno   : Posição da estrutura no arquivo.
int localizaStructPorCpf(char *pCpfDigitado)
{
  FILE *arq;
  int contBytes=0;
  tipoFrequentador estrutura;
  if (!(arq = fopen(ARQFREQUENT,"rb"))) 
      exit(1);//erro ao abrir o arquivo.
  while(fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     contBytes=ftell(arq); 
     if (strcmp(estrutura.cpf,pCpfDigitado)==0)
     {
           fclose(arq); // sempre fechar arquivo
           return contBytes - sizeof(tipoFrequentador); 
     }                                                
                                                     
  }
  fclose(arq); // sempre fechar arquivo
  return -1; 
}
// Subprograma 3
//  Objetivo  : Deletar um Frequentador.
//  Parâmetro : Apontador do frequentador.
//  Retorno   : Nenhum.
void deletaFrequentador(int apontador)
{
//Declaraçoes
  FILE *arq,*arqTemp;
  tipoFrequentador estrutura;
  int contBytes=0;
//instruções:      
  if (!(arq = fopen(ARQFREQUENT,"rb"))) 
     exit(1);
  if (!(arqTemp = fopen(ARQTEMP,"wb"))) 
     exit(1);
  while(fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     if (contBytes == apontador) 
        fseek(arq,sizeof(tipoFrequentador),1);  
     else         
        fwrite(&estrutura,sizeof(tipoFrequentador),1,arqTemp); 
     contBytes = ftell(arq);//contador de bytes recebendo o apontador.
  }
  fclose(arq);
  fclose(arqTemp);
  remove(ARQFREQUENT); 
  rename(ARQTEMP,ARQFREQUENT); 
  printf("Frequentador excluido com sucesso!\n");
  return;     
}
 

Relacionando todos os frequentadores que executaram pelo menos uma vez uma série de exercício definida pelo usuário:

 

Para fazer essa relação, a primeira coisa a fazer é pedir ao usuário qual a série que será pesquisada, verificar se ela existe no arquivo de atividades, caso exista, fazer a listagem dos frequentadores que executaram essa atividade com a série informada pelo usuário.

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
#define ARQATIVIDADE "dadosAtividades.bin"
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
}tipoFrequentador ;
typedef struct
{
  char cpf[MAX_CPF];
  int codigo;
  int dia;
  int mes;
  int ano;
} tipoAtividade;

void listaFrequentadores(tipoFrequentador estrutura);
void listaFrequentadoresSerie(int codigoSerie);

int main(void)
{
// Declaracoes
  int codigoSerie;
// Instrucoes
  printf("Digite o codigo da serie que foi executada:\n");
  scanf("%d",&codigoSerie);
  listaFrequentadoresSerie(codigoSerie);
  getch();
  return 0;
}
// Subprograma 1
//  Objetivo  : Fazer a listagem dos frequentadores.
//  Parâmetro : Estrutura de frequentadores.
//  Retorno   : Nenhum.
void listaFrequentadores(tipoFrequentador estrutura)
{
  printf("cpf = %s\n",estrutura.cpf);
  printf("nome = %s\n",estrutura.nome);
  printf("peso = %3.2f\n",estrutura.peso);
  printf("sexo = %c\n",estrutura.sexo);
  printf("data de inscricao: %d/%d/%d\n\n",estrutura.dia,estrutura.mes,estrutura.ano);
}
// Subprograma 2
//  Objetivo: verificar se algum cliente executou uma serie
//  Parâmetro: codigo da serie
//  Retorno: nenhum 
void listaFrequentadoresSerie(int codigoSerie)
{
  tipoAtividade atividades;
  tipoFrequentador frequentadores;
  FILE *arqAtividade, *arqFrequentador;
  int contador=0;
  if (!(arqAtividade = fopen(ARQATIVIDADE,"a+b")))
     exit(1);
  if (!(arqFrequentador = fopen(ARQFREQUENT,"rb")))
     exit(1);
  while (fread(&atividades,sizeof(tipoAtividade),1,arqAtividade))
  {
    if (atividades.codigo == codigoSerie)
    {
       rewind(arqFrequentador);
       while (fread(&frequentadores,sizeof(tipoFrequentador),1,arqFrequentador))
       {
           if (frequentadores.cpf == atividades.cpf)
           {
              listaFrequentadores(frequentadores);
              contador++;
           }
       }
    }
  }
  fclose(arqAtividade);
  fclose(arqFrequentador);
  if (!contador)
     printf("nenhum frequentador executou essa atividade!");
     
}
 

Lembre-se: para essa operação funcionar, seu código já deve ter a struct de atividades implementada!

 

Pesquisando os frequentadores matriculados na academia pelo nome:

 

A primeira coisa a fazer é pedir o nome a ser pesquisado pelo usuário, depois é só ler todos os registros do arquivo, comparar o nome digitado (usando a função strstr) com os nomes do arquivo e fazer a listagem dos nomes que são semelhantes ao que o usuário digitou. Observe a função que realiza essa operação:

 
// Subprograma 1
//  Objetivo  : Pesquisar nomes semelhantes ao digitado.
//  Parâmetro : Nome digitado.
//  Retorno   : Nenhum.
void pesquisaNomeSemelhante(char *pNome)
{
  FILE *arq;
  tipoFrequentador estrutura;
  int contador=0;
  if (!(arq = fopen(ARQFREQUENT,"rb")))
     exit(1);
  while (fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
     if (strstr(estrutura.nome,pNome))
     {
        listaFrequentadores(estrutura);
        contador++;
     }
  }
  if (!contador)
     printf("nenhum frequentador com esse nome foi encontrado!\n");   
}  
 

Note que todos os registros do arquivo são lidos, e quando um semelhante ao digitado é encontrado, a função que faz a listagem é chamada, veja o corpo dela:

 
// Subprograma 2
//  Objetivo  : Fazer a listagem dos frequentadores.
//  Parâmetro : Estrutura de frequentadores.
//  Retorno   : Nenhum.
void listaFrequentadores(tipoFrequentador estrutura)
{
  printf("cpf = %s\n",estrutura.cpf);
  printf("nome = %s\n",estrutura.nome);
  printf("peso = %3.2f\n",estrutura.peso);
  printf("sexo = %c\n",estrutura.sexo);
  printf("data de inscricao: %d/%d/%d\n",estrutura.dia,estrutura.mes,estrutura.ano);
} 
 

Agora veja um exemplo de código que pede para o usuário digitar um nome, e então faz a pesquisa:

 
#include <stdio.h>
#include <conio.c>
#define MAX_CPF 12
#define MAX_NOME 60
#define ARQFREQUENT "dadosFrequentadores.bin"
typedef struct
{
  char cpf[MAX_CPF];
  char nome[MAX_NOME];
  float peso;
  char sexo;
  int dia,mes,ano;
} tipoFrequentador;

void pesquisaNomeSemelhante(char *pNome);
void listaFrequentadores(tipoFrequentador estrutura);

int main(void)
{
// Declaracoes
  char nomeDigitado[MAX_NOME];
// Instrucoes
  printf("Digite o nome ou parte dele a ser pesquisado:\n");
  scanf("%s",nomeDigitado);
  pesquisaNomeSemelhante(nomeDigitado);
  getch();
  return 0;
}
// Subprograma 1
//  Objetivo  : Pesquisar nomes semelhantes ao digitado.
//  Parâmetro : Nome digitado.
//  Retorno   : Nenhum.
void pesquisaNomeSemelhante(char *pNome)
{
  FILE *arq;
  tipoFrequentador estrutura;
  int contador=0;
  if (!(arq = fopen(ARQFREQUENT,"rb")))
     exit(1);
  while (fread(&estrutura,sizeof(tipoFrequentador),1,arq))
  {
    if (strstr(estrutura.nome,pNome))
    {
       listaFrequentadores(estrutura);
       contador++;
    }
  }
  if (!contador)
    printf("nenhum frequentador com esse nome foi encontrado!\n");   
}
// Subprograma 2
//  Objetivo  : Fazer a listagem dos frequentadores.
//  Parâmetro : Estrutura de frequentadores.
//  Retorno   : Nenhum.
void listaFrequentadores(tipoFrequentador estrutura)
{
  printf("cpf = %s\n",estrutura.cpf);
  printf("nome = %s\n",estrutura.nome);
  printf("peso = %3.2f\n",estrutura.peso);
  printf("sexo = %c\n",estrutura.sexo);
  printf("data de inscricao: %d/%d/%d\n",estrutura.dia,estrutura.mes,estrutura.ano);
}