Staffer Group BR™

Fórum interativo totalmente gratuito!


 VisualizaçõesPermissão deste fórum:
Não podes responder a tópicos


CurtirDiretório deste fórum:
Fóruns » Principal »  » Tutoriais » Programação Externa

#1
 D'Leandro™

D'Leandro™
Fundador
Recadinho: Bem, depois de tantos tópicos e textos chegamos ao fim de nossa serie de tutoriais para iniciantes, logo planejo postar um nova série, mas vou dar tempo para que você possa se empolgar um pouco mais na programação...
Caso queira retornar ao indice inicial do curso, clique neste link.

Mas sem mais demoras, vamos ao tema desse último post. Nele falaremos sobre a gravação de dados em arquivos, pois de que vale um bom aplicativo se ele não guarda dados? Fechou o programa, perdeu tudo?? Negativo. Após esse post, você poderá criar programas realmente funcionais, gravando dados em arquivos (binários ou de texto).

Antes de começarmos a ver na programação como as coisas funcionam, precisamos entender o que é um arquivo. O arquivo nada mais é que um conjunto sequencial de dados em sua forma binária (0 e 1). Na programação, usualmente salvamos o arquivo em dois formatos diferentes: o formato ASCII e o formato binário. No formato ASCII, os dados são gravados na forma de caracteres, ou seja, caso você abra o arquivo em um editor de textos (como o Bloco de Notas ou o Gedit), você poderá ver os dados normalmente. Tais tipos de arquivos são úteis ao exportar um log, por exemplo. Assim, caso o usuário abra o arquivo, poderá ler os dados normalmente. Já no tipo binário, os dados são gravados na forma que se encontram na memória. Por exemplo, vamos supor que um inteiro seja representado por 0x0001A047 na memória. E vamos supor que isso valha 80. Ao gravar no arquivo, você gravará o correspondente binário de 80 (alguma coisa parecida com esse número hexadecimal). Dessa forma, se alguém abrir o arquivo com um editor de textos, não conseguirá distinguir muita coisa. Esse tipo de arquivo é bom para gravarmos os dados que o aplicativo irá manipular, dificultando alterações externas por usuários “espertinhos”. Ficou clara a diferença?

Na programação, os arquivos são controlados geralmente por um ponteiro (em C) ou por uma estrutura própria (em Pascal). Ao abrir um arquivo, o ponteiro localiza-se automaticamente no início do arquivo. A partir daí, vamos então lendo os dados, especificando a quantidade de informação a ser lida, até chegar ao fim do arquivo. Tal condição é obtida através de uma função que indica esse fim do arquivo.

Para começarmos a colocar a mão na massa, vamos fazer diferente dessa vez. Vamos criar um programa completo, em Pascal e em C, que demonstrará todos os conceitos que pretendo passar neste post. Será uma agenda eletrônica, que guardará o nome, a data de aniversário e o telefone do contato. Nesse aplicativo, será possível inserir um contato, buscar um contato, editar um contato e excluir um contato (conceito básico de CRUD - Create, Read, Update e Delete). Este aplicativo também será um tipo de revisão geral de tudo que vimos até aqui! Logo em seguida, vou explicá-lo passo a passo.

Primeiro, o programa em Pascal:
Código:
(*
 * Aplicativo de Agenda Eletrônica - versão em Pascal
 * Desenvolvido por Rafael D. Toledo
 * (rafaeldtoledo@gmail.com)
 * Baixado de http://striker07.wordpress.com
 * Compartilhe, use à vontade, mas cite a fonte! =)
 *)
 
program
  agendaEletronica;
 
uses
  crt, sysutils;
 
type
  contato = record
    nome: string[30];
    diaAniversario: integer;
    mesAniversario: integer;
    telefone: string[15];
  end;
 
function exibirMenu: integer;
var
  opcao: integer;
begin
  clrscr;
 
 writeln('     AGENDA ELETRONICA - striker07.wordpress.com');
  writeln;
  writeln(' 1. Inserir Contato');
  writeln(' 2. Buscar Contato');
  writeln(' 3. Atualizar Telefone');
  writeln(' 4. Excluir Contato');
  writeln(' 5. Encerrar');
  writeln;
  write(' Digite a opcao desejada: ');
  readln(opcao);
 
 exibirMenu := opcao;
end;
 
procedure gravarContato;
var
  meuContato: contato;
  arquivo: file of contato;
begin
  clrscr;
 
 writeln('     AGENDA ELETRONICA - INSERIR CONTATO');
  writeln;
  write(' Nome: ');
  readln(meuContato.nome);
  write(' Dia do Aniversario: ');
  readln(meuContato.diaAniversario);
  write(' Mes do Aniversario: ');
  readln(meuContato.mesAniversario);
  write(' Telefone: ');
  readln(meuContato.telefone);
 
 assign(arquivo, 'contatos.dat');
  {$I-} reset(arquivo); {$I+};
  if ioresult <> 0 then
    rewrite(arquivo);
 
 if filesize(arquivo) > 0 then
    seek(arquivo, filesize(arquivo));
 
 write(arquivo, meuContato);
  close(arquivo);
end;
 
procedure buscarContato;
var
  encontrado: boolean;
  busca: string[30];
  meuContato: contato;
  arquivo: file of contato;
begin
  encontrado := false;
  clrscr;
 
 writeln('     AGENDA ELETRONICA - BUSCAR CONTATO');
  writeln;
  write(' Nome do Contato: ');
  readln(busca);
 
 assign(arquivo, 'contatos.dat');
  {$I-} reset(arquivo); {$I+};
  if ioresult <> 0 then
  begin
    writeln;
    write(' Nada encontrado no arquivo!');
    sleep(1000);
  end
  else
  begin
    seek(arquivo, 0);
    while not eof(arquivo) do
    begin
      read(arquivo, meuContato);
      if meuContato.nome = busca then
      begin
        encontrado := true;
        writeln;
        writeln(' Nome: ', meuContato.nome);
        writeln(' Aniversario: ', meuContato.diaAniversario, '/', meuContato.mesAniversario);
        write(' Telefone: ', meuContato.telefone);
        sleep(2000);
      end;
    end;
 
   if encontrado = false then
    begin
      writeln;
      write(' Contato não encontrado!');
      sleep(1000);
    end;
 
   close(arquivo);
  end;
end;
 
procedure atualizarTelefone;
var
  encontrado: boolean;
  nome: string[30];
  telefone: string[15];
  contatoTemporario: contato;
  arquivoAntigo, arquivoAtualizado: file of contato;
begin
  encontrado := false;
 
 clrscr;
 
 writeln('     AGENDA TELEFONICA - ATUALIZAR TELEFONE');
  writeln;
  write(' Nome do Contato: ');
  readln(nome);
  write(' Novo Telefone: ');
  readln(telefone);
 
 assign(arquivoAntigo, 'contatos.dat');
  {$I-} reset(arquivoAntigo); {$I+};
  if ioresult = 0 then
  begin
    assign(arquivoAtualizado, 'temp.dat');
    {$I-} rewrite(arquivoAtualizado); {$I+};
    if ioresult <> 0 then
    begin
      writeln;
      write(' Falha na atualizacao do contato!');
      close(arquivoAntigo);
      sleep(1000);
    end
    else
    begin
      seek(arquivoAntigo, 0);
      while not eof(arquivoAntigo) do
      begin
        read(arquivoAntigo, contatoTemporario);
        if nome = contatoTemporario.nome then
        begin
          contatoTemporario.telefone := telefone;
          encontrado := true;
        end;
        write(arquivoAtualizado, contatoTemporario);
      end;
      close(arquivoAntigo);
      close(arquivoAtualizado);
      erase(arquivoAntigo);
      rename(arquivoAtualizado, 'contatos.dat');
 
     writeln;
      if encontrado then
        write(' Atualizacao realizada com sucesso!')
      else
        write(' não foi possivel encontrar o contato...');
      sleep(1000);
    end;
  end
  else
  begin
    writeln;
    write(' Nenhum contato encontrado!');
    sleep(1000);
  end;
end;
 
procedure excluirContato;
var
  encontrado: boolean;
  nome: string[30];
  contatoTemporario: contato;
  arquivoAntigo, arquivoAtualizado: file of contato;
begin
  encontrado := false;
 
 clrscr;
 
 writeln('     AGENDA TELEFONICA - EXCLUIR TELEFONE');
  writeln;
  write(' Nome do Contato: ');
  readln(nome);
 
 assign(arquivoAntigo, 'contatos.dat');
  {$I-} reset(arquivoAntigo); {$I+};
  if ioresult = 0 then
  begin
    assign(arquivoAtualizado, 'temp.dat');
    {$I-} rewrite(arquivoAtualizado); {$I+};
    if ioresult <> 0 then
    begin
      writeln;
      write(' Falha na exclusao do contato!');
      close(arquivoAntigo);
      sleep(1000);
    end
    else
    begin
      seek(arquivoAntigo, 0);
      while not eof(arquivoAntigo) do
      begin
        read(arquivoAntigo, contatoTemporario);
        if nome <> contatoTemporario.nome then
        begin
          write(arquivoAtualizado, contatoTemporario);
        end
        else
          encontrado := true;
      end;
      close(arquivoAntigo);
      close(arquivoAtualizado);
 
     erase(arquivoAntigo);
      rename(arquivoAtualizado, 'contatos.dat');
 
     writeln;
      if encontrado then
        write(' Exclusao realizada com sucesso!')
      else
        write(' não foi possivel encontrar o contato...');
      sleep(1000);
    end;
  end
  else
  begin
    writeln;
    write(' Nenhum contato encontrado!');
    sleep(1000);
  end;
end;
 
var
  opcao: integer;
 
begin
  repeat
    opcao := exibirMenu;
 
   case opcao of
      1: gravarContato;
      2: buscarContato;
      3: atualizarTelefone;
      4: excluirContato;
      5:
        begin
          writeln;
          write(' Encerrando...');
        end
      else
        begin
          writeln;
          write(' Opcao invalida!');
        end
    end;
    sleep(1000);
  until opcao = 5;
end.
Em C:
Código:
/*
 * Aplicativo de Agenda Eletrônica - versão em C
 * Desenvolvido por Rafael D. Toledo
 * (rafaeldtoledo@gmail.com)
 * Baixado de http://striker07.wordpress.com
 * Compartilhe, use à vontade, mas cite a fonte! =)
 */
 
#include <stdio.h>
#include <stdlib.h> // Para system() e sleep() (Linux)
#include <string.h>
#include <windows.h> // Para Sleep() - somente se for Windows
 
struct contato
{
    char nome[30];
    int diaAniversario;
    int mesAniversario;
    char telefone[15];
};
 
int exibirMenu(void);
void gravarContato(void);
void buscarContato(void);
void atualizarTelefone(void);
void excluirContato(void);
 
int main(void)
{
    int opcao;
 
   do
    {
        opcao = exibirMenu();
 
       switch (opcao)
        {
        case 1:
            gravarContato();
            break;
        case 2:
            buscarContato();
            break;
        case 3:
            atualizarTelefone();
            break;
        case 4:
            excluirContato();
            break;
        case 5:
            printf("\n Encerrando...");
            break;
        default:
            printf("\n Opcao invalida!");
        }
        Sleep(1000); // Se estiver usando Linux, é sleep(1);
    } while (opcao != 5);
 
   return 0;
}
 
int exibirMenu(void)
{
    int opcao;
 
   system("cls"); // Se estiver usando Linux, é system("clear");
 
   printf("\tAGENDA ELETRONICA - striker07.wordpress.com\n\n");
    printf(" 1. Inserir Contato\n");
    printf(" 2. Buscar Contato\n");
    printf(" 3. Atualizar Telefone\n");
    printf(" 4. Excluir Contato\n");
    printf(" 5. Encerrar\n\n");
    printf(" Digite a opcao desejada: ");
    scanf("%d", &opcao);
 
   return opcao;
}
 
void gravarContato(void)
{
    struct contato meuContato;
    FILE *arquivo;
 
   system("cls"); // Se estiver usando Linux, é system("clear");
 
   printf("\tAGENDA ELETRONICA - INSERIR CONTATO\n\n");
    printf(" Nome: ");
    fflush(stdin);
    gets(meuContato.nome);
    printf(" Dia do Aniversario: ");
    scanf("%d", &meuContato.diaAniversario);
    printf(" Mes do Aniversario: ");
    scanf("%d", &meuContato.mesAniversario);
    printf(" Telefone: ");
    fflush(stdin);
    gets(meuContato.telefone);
 
   arquivo = fopen("contatos.dat", "ab");
    if (!arquivo)
    {
        arquivo = fopen("contato.dat", "wb");
    }
 
   fwrite(&meuContato, 1, sizeof(struct contato), arquivo);
 
   fclose(arquivo);
}
 
void buscarContato(void)
{
    int encontrado = 0;
    char busca[30];
    struct contato meuContato;
    FILE *arquivo;
 
   system("cls"); // Se estiver usando Linux, é system("clear");
 
   printf("\tAGENDA ELETRONICA - BUSCAR CONTATO\n\n");
    printf(" Nome do Contato: ");
    fflush(stdin);
    gets(busca);
 
   arquivo = fopen("contatos.dat", "rb");
 
   if (arquivo)
    {
        fread(&meuContato, 1, sizeof(struct contato), arquivo);
        while (!feof(arquivo))
        {
            if (strcmp(busca, meuContato.nome) == 0)
            {
                printf("n Nome: %s\n", meuContato.nome);
                printf(" Aniversario: %d/%d\n", meuContato.diaAniversario, meuContato.mesAniversario);
                printf(" Telefone: %s", meuContato.telefone);
                Sleep(2000); // Se estivar usando Linux, é sleep(2);
                encontrado = 1;
                break;
            }
            fread(&meuContato, 1, sizeof(struct contato), arquivo);
        }
 
       if (!encontrado)
        {
            printf("\n Contato não encontrado!");
            Sleep(1000); // Se estivar usando Linux, é sleep(1);
        }
        fclose(arquivo);
    }
    else
    {
        printf("\n Nada encontrado no arquivo!");
        Sleep(1000); // Se estivar usando Linux, é sleep(1);
    }
}
 
void atualizarTelefone(void)
{
    int encontrado = 0;
    char nome[30], telefone[15];
    struct contato contatoTemporario;
    FILE *arquivoAntigo = NULL, *arquivoAtualizado = NULL;
 
   system("cls"); // Se estiver usando Linux, é system("clear");
 
   printf("\tAGENDA TELEFONICA - ATUALIZAR TELEFONE\n\n");
    printf(" Nome do Contato: ");
    fflush(stdin);
    gets(nome);
    printf(" Novo Telefone: ");
    fflush(stdin);
    gets(telefone);
 
   arquivoAntigo = fopen("contatos.dat", "rb");
    if (arquivoAntigo)
    {
        arquivoAtualizado = fopen("temp.dat", "wb");
        if (!arquivoAtualizado)
        {
            printf("\n Falha na atualizacao do contato!");
            Sleep(1000); // Se estivar usando Linux, é sleep(1);
            return;
        }
 
       fread(&contatoTemporario, 1, sizeof(struct contato), arquivoAntigo);
        while (!feof(arquivoAntigo))
        {
            if (strcmp(contatoTemporario.nome, nome) == 0)
            {
                strcpy(contatoTemporario.telefone, telefone);
                encontrado = 1;
            }
            fwrite(&contatoTemporario, 1, sizeof(struct contato), arquivoAtualizado);
            fread(&contatoTemporario, 1, sizeof(struct contato), arquivoAntigo);
        }
 
       fclose(arquivoAntigo);
        fclose(arquivoAtualizado);
 
       remove("contatos.dat");
        rename("temp.dat", "contatos.dat");
 
       if (!encontrado)
        {
            printf("\n não foi possivel encontrar o contato...");
        }
        else
        {
            printf("\n Atualizacao realizada com sucesso!");
        }
 
       Sleep(1000); // Se estiver usando Linux, é sleep(1);
    }
    else
    {
        printf("\n Nenhum contato encontrado!");
        Sleep(1000); // Se estivar usando Linux, é sleep(1);
    }
}
 
void excluirContato(void)
{
    int encontrado = 0;
    char nome[30];
    struct contato contatoTemporario;
    FILE *arquivoAntigo = NULL, *arquivoAtualizado = NULL;
 
   system("cls"); // Se estiver usando Linux, é system("clear");
 
   printf("\tAGENDA TELEFONICA - EXCLUIR TELEFONE\n\n");
    printf(" Nome do Contato: ");
    fflush(stdin);
    gets(nome);
 
   arquivoAntigo = fopen("contatos.dat", "rb");
    if (arquivoAntigo)
    {
        arquivoAtualizado = fopen("temp.dat", "wb");
        if (!arquivoAtualizado)
        {
            printf("\n Falha na exclusao do contato!");
            fclose(arquivoAntigo);
            Sleep(1000); // Se estivar usando Linux, é sleep(1);
            return;
        }
 
       fread(&contatoTemporario, 1, sizeof(struct contato), arquivoAntigo);
        while (!feof(arquivoAntigo))
        {
            if (strcmp(contatoTemporario.nome, nome) == 0)
            {
                encontrado = 1;
            }
            else
            {
                fwrite(&contatoTemporario, 1, sizeof(struct contato), arquivoAtualizado);
            }
            fread(&contatoTemporario, 1, sizeof(struct contato), arquivoAntigo);
        }
 
       fclose(arquivoAntigo);
        fclose(arquivoAtualizado);
 
       remove("contatos.dat");
        rename("temp.dat", "contatos.dat");
 
       if (!encontrado)
        {
            printf("\n não foi possivel encontrar o contato...");
        }
        else
        {
            printf("\n Exclusao realizada com sucesso!");
        }
 
       Sleep(1000); // Se estiver usando Linux, é sleep(1);
    }
    else
    {
        printf("\n Nenhum contato encontrado!");
        Sleep(1000); // Se estivar usando Linux, é sleep(1);
    }
}
Como podem perceber, é um programa razoavelmente grande (quase 300 linhas, em ambas as versões). Para facilitar as explicações, vamos analisar função por função, começando pela função principal (Pascal – linha 254; C - linha 28).

A função principal do aplicativo não tem nenhum segredo. Declaramos uma variável chamada opção que armazenará a escolha do usuário sobre o que fazer. Se você não entendeu alguma coisa do que foi feito aqui, não hesite em voltar nos posts anteriores e reler para entender. Aqui, estou assumindo que você já compreendeu as técnicas utilizadas anteriormente nessa série de posts. Então, como eu ia dizendo, fazemos uma escolha de acordo com a opção do usuário, chamando a função correspondente ao que ele escolheu. Essa opção é retornada pela função exibirMenu (Pascal - linha 23; C - linha 62). Esta função limpa a tela, também muito simples, exibe o menu na tela com as opções, lê a opção digitada pelo usuário e retorna. Somente isso.

Vamos começar a falar da parte importante desse programa, que é a manipulação de arquivos em si. Vamos começar pela função de inclusão, a função gravarContato (Pascal - linha 43; C - linha 80). Nesta função (estou usando a palavra função pra generalizar, mas gravarContato é um procedimento!), temos duas variáveis: um registro, do tipo contato, que declaramos com os campos nome, diaAniversario, mesAniversario e telefone (Pascal - linha 15; C - linha 14), e uma outra variável representando o nosso arquivo. Em Pascal, definimos que tipo de dados guardaremos no arquivo logo na sua declaração – no nosso caso, file of contato, já que guardaremos os contatos nele. Já em C, o tipo arquivo é mais genérico. Declaramos um ponteiro para o tipo FILE (sim, todas em maiúsculo). A partir dele, o controle do fluxo para o arquivo todo é de nossa responsabilidade. Prosseguindo, na primeira parte, simplesmente lemos os dados do usuário e o colocamos dentro do registro. No ponto em que estamos, não deve haver dúvidas sobre isso. O próximo passo, é realizarmos a abertura do arquivo. O processo de abertura é essencial, pois com ele tomamos o arquivo, impedindo que outras aplicações o acessem enquanto o estamos manipulando. Em Pascal, isso ocorre neste trecho:
Código:
assign(arquivo, 'contatos.dat');
{$I-} reset(arquivo); {$I+};
if ioresult <> 0 then
  rewrite(arquivo);
Primeiramente, ligamos a nossa variável a um arquivo físico através da função assign. Logo em seguida, fazemos uma chamada a função reset, que serve para abrir um arquivo já existente. Circundamos essa chamada com as diretivas de compilação {$I-} e {$I+}, para verificarmos posteriormente se houve erro. Ao usarmos tais diretivas, temos o resultado da operação na variável ioresult. Caso o valor presente seja diferente de 0, é sinal que houve algum erro – provavelmente porque o arquivo ainda não existe. Dessa forma, realizamos a abertura com a função rewrite. Essa função cria um novo arquivo, independentemente se existe ou não outro com mesmo nome. Caso exista, o mesmo será sobrescrito – por isso, tome certo cuidado ao utilizar tal função, ou poderá perder todos os seus dados!

Pronto! O nosso arquivo está, então, aberto e está aguardando realizarmos alguma coisa com ele. Vamos ver como fica esse mesmo procedimento na linguagem C:
Código:
arquivo = fopen("contatos.dat", "ab");
if (!arquivo)
{
    arquivo = fopen("contato.dat", "wb");
}
Temos o nosso ponteiro chamado arquivo, que receberá o retorno da função fopen. Esta função tem como argumentos o nome do arquivo (no nosso caso, contatos.dat) e em seguida o modo de abertura. Neste caso, utilizamos o modo ab - append & binary, ou seja, queremos adicionar alguma coisa após o fim do arquivo, que se trata de um arquivo binário. Caso o retorno da função seja nulo (NULL) – indicando que o arquivo não existe, por isso não é possível adicionar nada ao seu fim, abrimos então o arquivo para escrita, usando o modo wb - write & binary. Da mesma forma como em Pascal, esse modo sobrescreverá ou criará um novo arquivo.

Para gravarmos o nosso dado no arquivo, fazemos chamada a uma função de escrita. Em Pascal, chamamos a função write, passando pra ela onde iremos gravar (no caso, no arquivo), e o que iremos gravar (no caso, o nosso registro). Porém, antes disso, posicionamos o arquivo no seu fim, através da função seek. Verificamos se o tamanho do arquivo é maior que 0 (valor em bytes), e caso positivo, o posicionamos em seu final. Por fim, fechamos o arquivo usando a função close, que recebe o arquivo como argumento.

Em C, não precisaremos realizar o reposicionamento, pois caso o arquivo seja aberto no modo append, ele já estará automaticamente posicionado no fim do arquivo, e caso seja aberto no modo write, é porque não há arquivo, ou seja, o dado será gravado na posição 0. A função para a gravar o dado é um pouco mais complexa que em Pascal. Em C, utilizamos a função fwrite. Para ela, passamos primeiramente o endereço onde está o dado que desejamos gravar (por isso o &), logo em seguida, quantas vezes iremos gravar a informação (no caso, 1 vez), o tamanho da informação que será gravada (do tamanho de um registro do tipo contato – obtemos tal valor com a função sizeof) e por fim, onde tal informação será gravada – no arquivo. Por fim, fechamos o arquivo com a função fclose.

Pronto! A nossa informação já está gravada no arquivo contato.dat!

Vamos agora analisar o funcionamento da função buscarContato (Pascal - linha 73; C - linha 110). Temos uma variável que indica se o contato buscado foi encontrado ou não, uma variável que terá o nome do contato que está sendo buscado, um registro que armazenará os dados lidos do arquivo e o nosso arquivo. No início da função, pedimos ao usuário que digite o nome do contato a ser buscado. Em seguida, abrimos o arquivo para leitura. Em Pascal, caso não seja possível executar o comando reset, significa que o arquivo não existe – exibimos então uma mensagem de erro ao usuário (Nada encontrado no arquivo). Em C, abrimos o arquivo no modo rb - read & binary. Caso a função de abertura retorne NULL, significa que o arquivo não existe, portanto não é possível lê-lo – exibimos então a mensagem de erro. Caso tudo ocorra dentro dos conformes, vamos começar a varrer o arquivo em busca do contato digitado pelo usuário.

O que limitará a quantidade de acessos ao arquivo, será a função eof (Pascal) ou feof (C). Essa função retorna verdadeiro caso seja atingido o fim do arquivo. Porém, vale ressaltar uma diferença básica entre o funcionamento das duas funções. Em Pascal, a função retornará verdadeiro ao ler-se o último registro, ou seja, eu terei em meu registro o conteúdo do último registro do arquivo. Já em C, a função retorna verdadeiro quando eu tento ler dados que já ultrapassariam o fim do arquivo. Por exemplo, ao ler o último registro do arquivo, ela não retornaria verdadeiro. Apenas se eu tentar ler mais uma vez! Assim, quando a função feof me retornar verdadeiro, eu terei lixo no meu registro. É por esse motivo que, em Pascal utilizamos o while, com a leitura no início do corpo da repetição. Já em C, realizamos uma primeira leitura fora da repetição, e utilizamos o do-while, com a leitura ao final do corpo da repetição.

Em Pascal, para lermos o nosso arquivo, chamamos a função read, que recebe como parâmetros o arquivo de onde os dados serão lidos e o registro onde os dados lidos serão armazenados. Já em C, chamamos a função fread, que possui os mesmos parâmetros da função fwrite, com a uma leve diferença de significado – o registro onde serão armazenados os dados lidos do arquivo, a quantidade de leituras (sempre achei isso meio estranho…), a quantidade de dados lidos do arquivo, e o arquivo no qual os dados serão lidos. Caso o registro lido corresponda ao que o usuário está procurando, exibimos os dados na tela e setamos a variável encontrado (nota: achou estranho em C, essa variável ser inteira? Em C, como nativamente não existe o tipo booleano, as variáveis inteiras podem ser consideradas como booleanas, levando-se em consideração a regra: Falso = 0; Verdadeiro != 0. Porém, a partir de sua última especificação, o C99, o tipo bool foi especificado, adicionando-se o arquivo de cabeçalho stdbool.h). Após atingir o fim do arquivo, verificamos se o registro não foi encontrado – para exibirmos a mensagem ao usuário – e por fim fechamos o arquivo.

Vamos analisar, então, as últimas duas funções – atualizarTelefone (Pascal - linha 124; C - linha 157) e excluirContato (Pascal - linha 190; C - linha 221). Essas funções permitem diversas formas de implementação. Esta que lhes apresento não é a melhor, nem a mais otimizada, mas funciona e acredito que seja a mais simples de entender. Vou explicar a lógica antes de explicar o código. Vamos utilizar dois arquivos. O primeiro, será o arquivo de entrada, onde estão todos os registros já gravados. O segundo, será o arquivo de saída, que iremos regravar os dados. Na atualização, lemos um registro do arquivo de entrada, verificamos se é o arquivo a ser atualizado. Se não for, gravamos no arquivo de saída. Se for, atualizamos o telefone e também gravamos no arquivo de saída. Já na exclusão, o processo é bastante semelhante. Lemos um registro do arquivo de entrada, verificamos se é o registro a ser excluído. Se não for, gravamos no arquivo de saída. Se for, simplesmente o ignoramos e seguimos para o próximo. Ao final do processo, excluímos o arquivo original e renomeamos o arquivo atualizado para o nome que o outro arquivo tinha. Confuso? Talvez um pouco agora no início. Mas com a prática, você entenderá melhor a lógica e poderá criar a sua própria lógica – que pode ser infinitamente melhor que a minha.

Analisando o código, temos a variável indicadora se a atualização/exclusão ocorreu com sucesso, o nome do registro a ser atualizado/excluído, o telefone a ser atualizado (somente na função atualizarTelefone), o registro temporário que armazenará os dados a medida com que forem lidos do arquivo, e as duas variáveis representando os arquivos. Iniciamos a função pedindo os dados do usuário, abrimos o arquivo contatos.dat para leitura e o arquivo temp.dat para escrita. Assim, lemos todos os registros, realizamos a análise, e gravamos tudo no arquivo de saída (temp.dat). Após isso, fechamos os dois arquivos para que possamos realizar o processo de excluir e renomear. Em Pascal, utilizamos as funções erase que recebe uma variável vinculada a um arquivo – esse vínculo foi criado ao chamarmos a função assign lá no topo da função. Já para renomearmos, chamamos a função rename, passando o arquivo a ser renomeado e o seu novo nome. Em C, chamamos a função remove, passando o nome do arquivo a ser excluído, e em seguida a função rename, passando o nome do arquivo a ser renomeado, seguido pelo novo nome do arquivo.

Bom, pode parecer um bocado de informação de uma só vez, mas como já disse antes: somente com a prática você vai se familiarizar com tais técnicas. Eu mesmo posso dizer: quando estava aprendendo, isso me pareceu extremamente complicado, complexo, pra não dizer sem sentido. Mas posso dizer também que, ao superar essa etapa (ou este medo?), você estará preparado para seguir em frente e começar a desbravar temas mais “complexos”.

Agora, pra fecharmos esse post, vou mostrar um exemplo simples de como escrever e ler de um arquivo texto.

Em Pascal:
Código:
program
  arquivoTexto;
 
uses
  crt;
 
var
  texto: string[255];
  arquivo: text;
 
begin
  writeln('Vamos escrever uma frase no arquivo.');
 
 assign(arquivo, 'arquivo.txt');
  rewrite(arquivo);
  writeln(arquivo, 'Testando arquivos txt.');
  close(arquivo);
 
 writeln('Va até o diretorio e verifique o arquivo.txt');
  write('Pressione uma tecla para continuar. . .');
  readkey;
 
 writeln;
  writeln('Agora vamos ler o conteudo gravado.');
  reset(arquivo);
  readln(arquivo, texto);
  writeln('Conteudo do arquivo: ');
  writeln(texto);
  close(arquivo);
 
 write('Pressione uma tecla para continuar. . .');
  readkey;
end.
Em C:
Código:
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    char texto[255];
    FILE *arquivo;
 
   arquivo = fopen("arquivo.txt", "w");
    fprintf(arquivo, "Testando arquivos txt.");
    fclose(arquivo);
 
   printf("Va até o diretorio e verifique o arquivo.txt\n");
    system("pause");
 
   printf("\nAgora vamos ver se o conteudo foi gravado.\n");
    arquivo = fopen("arquivo.txt", "r");
 
   fgets(texto, 255, arquivo);
    printf("Conteudo do arquivo:\n%s\n", texto);
    fclose(arquivo);
 
   system("pause");
    printf("\n");
 
   return 0;
}
Bom, neste exemplo, simplesmente gravamos uma string em um arquivo e depois lemos novamente e exibimos na tela. Em Pascal, a única “novidade” seria o tipo text. Esse tipo representa o arquivo texto, fazendo com que o manipulemos como se fosse a própria tela ou a entrada do teclado, ou seja, utilizando as funções writeln e readln. Em C, o que diferencia para o uso de arquivos binários, primeiramente, é que no modo de abertura, não temos a letra b. Assim, ao abrir o arquivo para leitura, usamos r, para escrita, usamos w e assim por diante. Para escrever e ler do arquivo, temos versões das funções printf e scanf, com o prefixo f. Dessa forma, usamos fprintf e fscanf da mesma forma que usamos normalmente, só que passando também o arquivo como parâmetro. Nesse exemplo em específico, eu usei fgets, já que a nossa frase continha espaços (que o scanf interpreta como fim de linha). Nessa chamada, passamos a variável que receberá o texto, o tamanho máximo de bytes a serem lidos (pra que não ocorra o problema de estourar a capacidade de nossa string), e o arquivo de onde o texto será lido. Com o gets, a leitura é interrompida quando encontra-se um “enter” ou quebra de linha. No mais, nada de novidade nos programas acima.

Bom pessoal, é isso. O post ficou longo, demorou pra ficar pronto, mas acho que deve ajudar o pessoal aí. Assim, encerramos essa primeira série de posts. Fico imensamente grato a todos que visitam o blog. Acho que atingi meu primeiro objetivo, que era o de passar o conhecimento que eu tenho em programação de uma forma descomplicada pra quem está começando. Lá no primeiro post, em dezembro de 2008, mal sabia eu o quão certo essa ideia daria. Hoje, já temos mais de 16.000 visitas e pretendo aumentar cada vez mais a quantidade de pessoas ajudadas por esse blog.

Deixo, por ora, meu muito obrigado, e que continuem acessando, pois em breve, teremos novidades por aqui.

Este artigo foi escrito por Rafael Toledo e publicado no site rafaeltoledo.net
Abraço a todos :D