Programação

sexta-feira, 7 de outubro de 2011

Módulo 7 - Ficheiros

FICHEIROS

Introdução
• Os dados utilizados até aqui, existiram na memória principal durante a execução do seu programa.  
    de c
  • Terminada a execução do programa, estes dados desaparecem
  •  
  • O que interessa na gestão de dados, é armazenar os dados de forma permanente.

  • Isto só se consegue armazenando os dados em ficheiros externos ao programa que executamos
  • Em Ficheiros que podemos escrever, leitura, modificar e armazenar os dados nele contidos.

  • E que mais tarde podemos recuperar para utilizar novamente.
  • Vamos portanto aprender aqui como declarar, criar e manipular estes ficheiros.

Exemplo
Suponha que desenvolve um programa para a calcular a média aritmética da primeira prova de frequência de uma turma e passado algum tempo realiza uma segunda prova de frequência para a mesma turma e pretender calcular a média aritmética das classificações obtidas em ambas as provas. Será que tem de introduzir novamente os dados relativos à primeira prova de frequência?

Tipos de periféricos
Os dados de entrada para um programa podem ser fornecidos a partir de periféricos de entrada, tais como, teclado, rato, leitor de código de barras, etc.

Os dados de saída de um programa podem ser enviados para diversos periféricos de saída, tais como, monitor, impressora, etc.

Existem periféricos de entrada/saída, tais como, discos, que permitem operações de leitura/escrita.

Independentemente do tipo de periférico, a Linguagem C, processa todas as entradas e saídas de dados através de streams.

STREAMS
É um conjunto sequencial de dados, isto é, um conjunto de Bytes, sem qualquer estrutura interna.
Vantagem dos streams na sua utilização na entrada/saída de dados é que é independente do periférico que se está a utilizar.

Em C cada stream está ligado a um ficheiro, mas pode não corresponder fisicamente a um ficheiro existente em disco.


Tipos de Ficheiros
    Ficheiro texto é processado como uma sequência de caracteres ( contém texto constituído por caracteres, pontuação, espaço em branco, tab, newLine \n)

Os caracteres dos ficheiros de texto são representados no código ASCII e podem ser lidos ou escritos por qualquer processador de texto em qualquer computador, tendo como grande vantagem a portabilidade.

   Ficheiro binário é processado como uma sequência de bytes, codificado em binário (caracteres existentes na tabela ASCII, caracteres de controlo e caracteres especiais, caracteres sem representação visível \0)    

Num ficheiro binário os dados são armazenados como bytes e a representação usada é a mesma que os dados binários armazenados na memória central do computador. Em geral os dados binários não são muito portáveis


Nota:  Quer os ficheiros binários quer os de texto armazenam os dados como sequências de bits.
A diferença verifica-se no modo como os programas lêem ou escrevem para estes ficheiros

A informação guardada em ficheiro pode ser acedida e gerida de dois modos distintos:

Modo sequencial - ficheiro de texto -  
Neste modo os elementos do ficheiro são acedidos sequencialmente, em posições consecutivas. Os ficheiros de texto, constituídos por informação estruturada em linhas, logo, elementos de comprimento variável terminados por uma marca de fim de linha, são geridos em modo sequencial.

Modo de acesso aleatório ou directoficheiros binários-. Neste modo os elementos do ficheiro, constituídos por elementos de dimensão fixa (número de bytes constante), são acedidos por ordem arbitrária.



Declaração de ficheiros num programa em linguagem C:

FILE  *nome_ficheiro_no_programa;     // FILE em maiúsculas


Exemplo: FILE  *fich;    // fich é um apontador para o tipo FILE

Antes de criar ou abrir um ficheiro externo temos que declarar uma variável do tipo FILE que é nome interno no programa.
O que  interessa aqui é este nome do ficheiro no interior do programa que vai ser usado para manipular o ficheiro em disco.

Operações básicas sobre ficheiros

Abertura de um ficheiro     -  Função fopen

O protótipo da função está no header file  stdio.h

Ponteiro_tipo_FILE  =   fopen (    nomeFicheiroDisco ,  Mod oAcessoFic  )    

fich = fopen( localização \\nomeficheiro, modoacesso );

Exemplo:  
        fich =  fopen (“conto.doc”,   “w”  );    // e indicamos qual é o modo de acesso

Cria e Abre o ficheiro e é feita uma relação entre o nome interno (“fich”) e o nome externo (“conto.doc”)

/* Modos de Acesso no momento de abrir um ficheiro com fopen() */

“r”- read:  abre o ficheiro só para leitura. O ficheiro tem que existir em disco.
“w” – write:  Abre o ficheiro para escrita; se existir o ficheiro será rescrito. Se não existir, cria o ficheiro
a”append : abre o ficheiro para escrever no fim do ficheiro; se não existir, cria o ficheiro  

r+” abertura do ficheiro para escrita e leitura; se existe reescreve;
w+” abertura do ficheiro para escrita e leitura; se existe apaga e cria um novo;
a+” abertura do ficheiro para escrita e leitura; adiciona no fim dum ficheiro existente

Por default, os ficheiros são abertos em modo de texto, pelo que o uso do modificador “t” não é necessário.



Modo Texto e Modo Binário
Por defeito, a abertura de um ficheiro é realizada considerando este como um ficheiro texto

Para abrir um ficheiro em modo binário é necessário acrescentar um b ao modo de abertura
Ex:    “wb”

Ficheiro texto – texto constituído por caracteres, pontuação, espaço em branco, tab, newLine \n

Ficheiro binário – caracteres existentes na tabela ASCII, caracteres de controlo e caracteres especiais, caracteres sem representação visível \0,


EXERCÍCIO: Complete os programas



a) programa para escrever num ficheiro de texto

#include <stdio.h>
main()
{
            FILE *         ;
                 =fopen( “texto.txt”,         ”   ”   );
}


b) programa para ler um ficheiro binário

#include <stdio.h>
main()
{
                        *fich      ;
fich=                  (“Exerc.txt”,”     ”);
fclose(                ) ;
}



Fecho de um ficheiro     função fclose ();

Utiliza-se:      fclose( fich );    //fecha o ficheiro fich  em que a variável apontador para FILE 


Funções de escrita /Leitura de dados num ficheiro

fprintf escreve no ficheiro                fprintf  (nome_ficheiro,  formatação saída + texto, variáveis )

fscanf  lê do ficheiro                          fscanf (nome_ficheiro,  formatação_entrada, variáveis)

fputc() – escreve 1 caracter no ficheiro                 fputc(caracter , ficheiro);
fgetc() leitura de 1 caracter do ficheiro caracter= fgetc(ficheiro);
fputs() inserir 1 string no ficheiro                      fputs(string, ficheiro);

fgets() leitura de 1 string:                      parâmetros de fgets (string, tamanho, ficheiro);

Recordar funções

putc(caracter) ;                      puts(string);
getc()                                       gets ()           



EXEMPLO
#include <stdio.h>
main()
{
            char nome[20];
            FILE *f;
            f = fopen("Texto.txt",  "w");     //abre arquivo para escrita
           
//pede ao utilizador e lê o nome introduzido
printf("Digite 1 nome: ");
            gets(nome);

//escreve no ficheiro uma string que está na variável nome
            fprintf (f, “%s  “, nome);    

            fclose( f );       //fecha arquivo criado
}


 //Lê do ficheiro o nome e apresenta-o no ecrã
#include <stdio.h>
main()
{
            char nome[20];
            FILE *f;
            f=fopen("Texto.txt","r");

            fscanf(f,  "%s",  nome   );

            printf("Nome do ficheiro: %s  \n",    nome    );
            fclose(f);
}




Exercício1: //pedir ao utilizador o nome e a nota de PSI que deseja e escrever os dados no ecrã
#include <stdio.h>
main()
{           char nome[20];      FILE *f;
            f =  fopen(" Dados.dat",   "w");

           printf(“ Nome: “);
           gets(nome);
            do
      {     printf(“ Nota: “);
                         scanf(“%d”, &nota);
            } while (  nota <0  || nota >20);     //faz   enquanto nota errada

            fprintf(f,  "%s   \n   %d  \n  ", nome, nota);
            fclose( f );
}


Exercício 2: Abrir ficheiro e ler o nome e a nota e apresentar os dados no ecrã



Resolução

#include <stdio.h>               /* Criar um ficheiro de texto desde o teclado. Escreva um conto */

#include <string.h>                 // Utilização de fopen() e fprint();



void main()

{ FILE *fich;           /* Declaramos um ponteiro a um ficheiro  */

char linha[80];           
  int total = 1;
              /* Abaixo: abrir novo ficheiro para escrita de texto verificando se OK */
fich = fopen("conto.doc", "w+t"));
//Ler 4 linhas de texto
for ( i=1;  i<=4  ; i++ )
 {     printf("\n escreva uma linha de texto do conto: ");
         gets(linha);
         fprintf( fich, "%s\n", linha);         



Podemos utilizar este código se quisermos que escreva uma mensagem de erro se não for possível abrir o ficheiro
 fich = fopen("conto.doc", "w+t");
if ( fich == NULL)
{   printf( "não podemos abrir o ficheiro \n");
     exit(1);
 }  

/* Verificamos se foi possível abrir o ficheiro ou não */



Usou-se a função exit(int num) (de stdlib.h) que permite terminar um programa, devolvendo números diferentes, conforme o tipo de erro, que podem ser lidos pelo sistema operativo.



FICHA DE TRABALHO
1.     Qual a função que serve para criar ou abrir um ficheiro?________________ E qual a função que fecha um ficheiro?____________
2.     Indique 2 funções que permitem escrever texto num ficheiro de texto__________________________________________________
3.     Indique 2 funções que permitem ler texto de um ficheiro de texto_________________________________________________
4.     Qual o ciclo/estrutura de repetição que utiliza para validar a entrada de um valor, isto é, que obriga a repetir quando um valor não é válido?__________________________________________________________________
5.     Para indicar o modo de acesso de escrita utiliza-se____, e para o modo de acesso de leitura utiliza-se _____ e acrescentar ____
6.     Declare uma variável apontador do tipo ficheiro_________________________________________
7.     Qual a função que detecta o fim do ficheiro?__________________________



8.     Faça um programa em C que peça ao utilizador o seu clube de futebol e depois escreva no ficheiro a resposta do utilizador.


9.     Faça um programa em C que leia o conteúdo do ficheiro criado no programa anterior e apresente-o no ecrã.


10.   Faça um programa que peça ao utilizador que ponha em prática a sua veia poética... e que introduza 4 versos de um poema


 FUNÇÃO QUE DETECTA O FIM DO FICHEIRO


Função  feof( ficheiro)             Fim de Ficheiro -   End Of File  - EOF   - detecta fim do ficheiro


Imagine o conto criado anteriormente. Agora vamos ler caracter a caracter…  usar função   fgetc e  feof

#include <stdio.h>

void main()
{char c;   FILE *fich;  

 fich = fopen (“c:\\conto.doc", "r");       /* abrir o ficheiro para leitura */

while (   !( feof  ( fich) )        /*REPETE enquanto não encontra fim do ficheiro */
   { c=  fgetc (fich );                /* devolve cada caracter lido do ficheiro*/

    printf("%c", c);      // escreve no ecrã o caracter lido anteriormente do ficheiro
    }

fclose(fich); /* fechar o ficheiro previamente aberto */
}


//pedir o nome do ficheiro ao utilizador e abri-lo e escrever o que nele está contido
#include <stdio.h>
void main()
{      char  nm[20] ,  ch  ;   FILE *fich;

printf( “\n Introduza o nome do ficheiro que quer abrir “);
scanf(“%s”, nm); 
fich =fopen(nm, “r”);      //abre ficheiro para leitura
if ( fich ==NULL)
 {printf(“\n Impossível abrir ficheiro \n ”); exit(0); }

while ( ! feof (fich) )  
   {     ch= fgetc(fich);    /* devolve próximo caracter do ‘stream’ */
          printf("%c", ch);     // escreve no ecrã caracter a caracter
}
   fclose(fich);
}


Ler uma linha de um ficheiro                fgets( variavel_string,   strlen(tipo)+1,   ficheiro)



Exercício  

Escrever um programa que crie um ficheiro de texto contendo 4 nomes de cidades e respectivas temperaturas médias num dado dia.

Exercício  Ler o conteúdo do ficheiro criado no exemplo anterior. Determinar média.



outros EXERCÍCIOS DE FICHEIROS DE TEXTO
1) // Pedir nomes e idades de 10 alunos e escrever todas as informações num ficheiro

2) /Abrir o ficheiro Alunos; escrever os dados no ecrã;  determinar a média de notas ;

3) Abrir ficheiro e escrever só os alunos com positiva

.       
       4) Faça um programa em C que peça ao utilizador o nome e idade de n pessoas  e depois escreva os dados num  ficheiro texto DadosID.txt
5) Programa em C que leia o conteúdo do ficheiro criado no programa anterior e apresente-o os dados no ecrã. 
Determine a média de idades. Determine quantos alunos são maiores de  idade. 




Processamento de ficheiros em binário

Os ficheiros de texto contém ‘\n’ (mudança de linha) que identifica e separa os caracteres existentes no ficheiro; estão organizados por linhas

Ficheiros binários –não são de texto- são ficheiros de dados, executáveis, jogos, etc..
Não estão organizados por linhas;

São usadas operações de Acesso Directo utilizadas só para ficheiros binários.

Podemos escrever dados em blocos de memória em disco- por exemplo, escrever um vector completo de uma vez só em disco.

Função de leitura que permitem acesso directo: fread
Função de escrita que permitem acesso directo: fwrite

      fwrite (    variável    ,  sizeof (  tipo  ),   n_elementos ,  ficheiro);      /* escreve    em ficheiro com sizeof bytes */

      fread (  variaável      , sizeof( tipo  ), n_elementos , ficheiro ) ;        /* Ler   sizeof  bytes  do ficheiro   */

// as funções devolvem o nº de valores que leram

Exercício
Programa que leia para um vector 10 nºs inteiros; e escreva esses valores em disco no ficheiro “dadosvector.txt”
#include <stdio.h>
main ()
{   FILE *f;    int  V[10], i ;
     // ler dados para vector
     for (i=0; i<=9 ; i++ )
         {   printf (" Indique o %dº número :   ");
             scanf("%d",  &V [i] ) ;
          }
     = fopen(“dadosvector.txt”, “wb”);     //acrescenta-se ao w um b de binário
     fwrite ( V,  sizeof(int) , 10, f   );      // vector, sizeof(int), 10 elementos, ficheiro
    fclose(f);
}


Exercício: 
Programa que leia do ficheiro em disco o vector de 10 elementos e mostra-os no ecrã
main ()
{   FILE *f;    int  V[10], i ;
     // ler dados para vector

     f= fopen(“dadosvector.txt”, “rb”);     //acrescenta-se ao r um b de binário

     fread ( V,  sizeof(int) , 10, f   );   // vector, sizeof(int), 10 elementos, ficheiro
    
      //escreve  o código no ecrã os elementos do vector



fclose(f);
}





Exercício:
programa que leia do ficheiro em disco os 10 elementos mas sem recorrer ao vector, e mostrar-los um a um no ecrã

// variável simples necessita de &  (endereço)

while fread ( &num ,  sizeof(int) , 1, f   )    )       // lê 1 elemento do ficheiro
            printf( “ %d  \n  ” , num );                           //escreve no ecrã



// não de usa EOF pois pode dar erro



Estruturas: typedef, struct



 Exercício: /* Programa para criar uma ficha de uma pessoa -- ler os dados --de 3 pessoas */

#include <stdio.h>                                           

#include <string.h>



typedef struct ficha

  {    char nome[35];   

       int idade;   
       char telefone[10];         // declaração de 3 campos
  };

// função para Ler dos Dados de 1 pessoa
ficha  Ler_ficha_Pessoa( )
{ ficha p ;                                 // p é uma variável do tipo struct ficha com 3 campos
      printf("\nNome: ");   gets(  p. nome);
      printf("idade: ");       scanf("%d", &p.idade);       // fflush(stdin);
      printf("telefone: ");   scanf("%s", p.telefone);    //fflush(stdin);
   return (p);
}    /* ----  devolve  a ficha (dados) de uma pessoa ----*/

void Escreve_Dados_Pessoa( ficha p )    // Entra 1 ficha (dados) de 1 pessoa e escreve esses dados
{    printf("\n Nome: %s", p.nome);
     printf("\n telefone:%s", p.telefone);
     printf("\n idade: %d", p.idade);
}

void main()
{ ficha  pessoas[3] ;         /*criamos um array com o novo tipo ficha: um array de estruturas */

for (int i = 0; i < 3; i++)
  {   printf("\nPor Favor dê os dados da %dª pessoa:",   i+1 );
     
       pessoas[ i ] = Ler_ficha_Pessoa();   // ou

       //     printf("\nNome: ");   gets( pessoas[ i ]. nome);
       //     printf("idade: ");       scanf("%d", &pessoas[ i ].idade);       // fflush(stdin);
       //   printf("telefone: ");   scanf("%s", pessoas[ i ].telefone);    //fflush(stdin);
    }

printf("\nDados das Pessoas registadas: ");
for (i=0; i < 3; i++)
        Escreve_Dados_Pessoa ( pessoas[i] );   //a função recebe 1 ficha - argumento- e escreve os dados
}  //fim


//Se houver problemas na leitura de dados do tipo char -  Utilizar fflush(stdin);  
 Se o ficheiro stdin tinha output pendente para escrever, esta função escreve os dados pendentes. Em termos práticos limpa o teclado. Utilizada porque scanf() as vezes cria problemas.



Exercício:
 /* Programa que escreve os dados –ficha- de 3 alunos do ficheiro “alunos” */
#include <stdio.h>                  
#include <conio.h>                 

typedef struct ficha                   //estrutura com 3 campos
{ char nome[30];     int idade;    float peso; 
}

ficha  Ler_Dados_Aluno (ficha a)
{   printf("\nNome: ");    gets(a.nome);                       fflush(stdin);
    printf(" idade: ");       scanf("%d", &a.idade);         fflush(stdin);
    printf(" peso: ");     scanf("%f", &a.peso);             fflush(stdin);
    return (a);
/*--------------------------------------------------------------------*/




void main ( )
{ FILE *fich ;       ficha aluno;
          fich = fopen ("\\Dados", "w+b") ;

for (int i =1; i < 4;i++)
{
      printf("\nPor Favor dê os dados do %dº aluno:",   i  );
      printf("\nNome: ");   gets( aluno.nome );                 // fflush(stdin);
      printf(" idade: ");      scanf("%d", &aluno.idade);      // fflush(stdin);
      printf(" peso: ");       scanf("%f", &aluno.peso);         // fflush(stdin);

      fwrite (&aluno, sizeof (ficha),  1,  fich);        /* escreve aluno em ficheiro com sizeof bytes */

  }  //pode ser  fwrite (&aluno, sizeof (aluno),  1,  ficheiro);

  fclose(fich);
}      /*-------------------------------------------------------------------*/


 fwrite(   endereço_registo,   tamanho_registo, 1,     ficheiro) ;

fread(   endereço_registo,   tamanho_registo, 1,     ficheiro) ;


 Exercício:
/* Programa que vai ler as 3 fichas criadas no ficheiro “alunos” */

#include <stdio.h>                  
#include <conio.h>
#include <string.h>

typedef struct  ficha
{ char nome[30];           int idade;       float peso;   
}    ;

void Escreve_Dados_Aluno (ficha a)
{    printf("\nNome: %s",  a.nome );
     printf("\t idade: %d", a.idade );
     printf("\t peso: %.1f", a.peso) ;
}

void main(void)
{  FILE *fich;       ficha aluno;     int i;

if ((fich= fopen("\\Dados", "r+b")) == NULL)
  {   printf  ( "Não podemos abrir ficheiro alunos. \n");
      exit(1);
}


while (   fread (&aluno, sizeof(ficha), 1, fich )   )      
        Escreve_Dados_Aluno ( aluno) ;
   fclose(fich);
}

Exercício:
// programa que utiliza fseek() mover o ponteiro f no stream

Ficheiros I/O --        fread(),      fwrite(),       fseek()

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

void main()
{  char s1[50];      FILE *f;                /* declara um ponteiro ficheiro   */

   char frase[ ] = "Isto é um teste para os meninos de Informática.";

    if ((   f = fopen("\\mensagem", "w+t")) == NULL)
        { printf("Não pode abrir ficheiro para escrever.\n");       
           exit(0); 
        }
    fwrite (frase,  strlen(frase)+1 , 1,  f ) ;            // escreve conteúdo de frase no stream f

// após escrever em f, o ponteiro aponta ao fim de f
fseek ( f , SEEK_SET, 0);         // recolocamos o ponteiro de f apontando ao seu byte 0

fread ( s1 , strlen(frase)+1, 1, f );             // ler mensagem do ficheiro e colocar na string s1

printf("%s \n", s1 );          // Imprime o conteúdo da string s1

 fflush(f);   
 fclose(f);

}



Ficheiros I/O: acesso directo a um registo

typedef struct  ficha
{ char nome[30];           int idade;       float peso; 
   }    ;

void Escreve_Dados_Aluno (ficha a)
{    printf("\nNome: %s",  a.nome );     
      printf("\t idade: %d", a.idade );     
      printf("\t peso: %.1f", a.peso) ;
}

void main(void)
{ int  pos, n ; FILE *fich
;      ficha aluno;


if ((fich = fopen("\\Dados", "r+b")) == NULL)
{   fprintf (stderr, "Não podemos abrir ficheiro clientes. \n");
    return;
}
printf(“\n Indique número do cliente sff: “); 
scanf(“%d”, &n);

fseek( fich, sizeof (ficha )*(n-1), SEEK_SET);

if ( ! ( fread (&aluno, sizeof(ficha), 1, fich) )  )  
        printf("\n Erro na leitura de alunos");

printf(“\n\n Dados do %d aluno \n “, n);   
Escreve_Dados_Aluno ( aluno);
fclose(fich);





Pedir versos ao utilizador e escrevê-los num ficheiro texto - pára até digitar tecla ESC


#include<dos.h>
#include<conio.h>
#include <stdio.h>
#define Esc_Key  27



 main()
 {

     while ( 1)                                            //kbhit()

     {    // pede e lê o verso 
          // escreve o verso dado pelo utilizador no ficheiro
         if (getch()==Esc_Key)            
                  break;                           // se estiver dentro de um menu sai do switch
      



              //  usar  exit(1);   em vez de break;    se for  um programa sem menu para terminar o  programa ;

   
     }

  getch();

 }


Sem comentários:

Enviar um comentário