Arquivos Em C

16
IMES – Centro Universitário São Caetano do Sul - CIÊNCIA DA COMPUTAÇÃO - 2º ANO ESTRUTURAS DE DADOS - Prof. Edson Pinheiro Pimentel ARQUIVOS EM C Existem dois conjuntos de funções de E/S com arquivos na linguagem C. Num primeiro ponto, tem-se a E/S ANSI (com buffer ou formatada) e, em termos mais específicos, tem-se a E/S UNIX (sem buffer ou não formatada). Uma ênfase maior é dada ao primeiro conjunto pela portabilidade deste sistema de entrada e saída com arquivos. Existem dois tipos possíveis de acesso a arquivos na linguagem C : sequencial (lendo um registro após o outro) e aleatório (posicionando- se diretamente num determinado registro). O sistema de arquivos na linguagem C é definido para manipular uma série de dispositivos, tais como terminais, acionadores de disco e outros. Estes dispositivos são vistos como arquivos lógicos em C, denominados STREAM (abstração do dispositivo). O dispositivo real é denominado ARQUIVO (impressora, disco, console e outros). Um STREAM é associado a um ARQUIVO por uma operação de abertura do arquivo e, a partir da associação, todas as demais operações de escrita e leitura podem ser realizadas. A Tabela 1 apresenta as principais funções da linguagem C para manipulação de arquivos. Função Ação fopen() Abre um arquivo Fclose () Fecha um arquivo putc() e fputc() Escreve um caractere em um arquivo getc() e fgetc() Lê um caractere de um arquivo fseek() Posiciona em um registro de um arquivo fprintf() Efetua impressão formatada em um arquivo fscanf() Efetua leitura formatada em um arquivo feof() Verifica o final de um arquivo fwrite() Escreve tipos maiores que 1 byte em um arquivo fread() Lê tipos maiores que 1 byte de um arquivo Tabela 1 - Funções do padrão ANSI para manipulação de arquivos O sistema de entrada e saída do ANSI C é composto por uma série de funções, cujos protótipos estão reunidos em stdio.h . Todas estas funções trabalham com o conceito de "ponteiro de arquivo". Este não é um tipo propriamente dito, mas uma definição usando o comando typedef . Esta definição também está no arquivo stdio.h. Podemos declarar um ponteiro de arquivo da seguinte maneira: 1 FILE *Arquivo;

description

Uma Introdução À Linguagem C

Transcript of Arquivos Em C

Page 1: Arquivos Em C

IMES – Centro Universitário São Caetano do Sul - CIÊNCIA DA COMPUTAÇÃO - 2º ANO – ESTRUTURAS DE DADOS - Prof. Edson Pinheiro Pimentel

ARQUIVOS EM C

Existem dois conjuntos de funções de E/S com arquivos na linguagem C. Num primeiro ponto, tem-se a E/S ANSI (com buffer ou formatada) e, em termos mais específicos, tem-se a E/S UNIX (sem buffer ou não formatada). Uma ênfase maior é dada ao primeiro conjunto pela portabilidade deste sistema de entrada e saída com arquivos.Existem dois tipos possíveis de acesso a arquivos na linguagem C : sequencial (lendo um registro após o outro) e aleatório (posicionando-se diretamente num determinado registro). O sistema de arquivos na linguagem C é definido para manipular uma série de dispositivos, tais como terminais, acionadores de disco e outros. Estes dispositivos são vistos como arquivos lógicos em C, denominados STREAM (abstração do dispositivo). O dispositivo real é denominado ARQUIVO (impressora, disco, console e outros). Um STREAM é associado a um ARQUIVO por uma operação de abertura do arquivo e, a partir da associação, todas as demais operações de escrita e leitura podem ser realizadas. A Tabela 1 apresenta as principais funções da linguagem C para manipulação de arquivos.

Função Açãofopen() Abre um arquivoFclose () Fecha um arquivoputc() e fputc() Escreve um caractere em um arquivogetc() e fgetc() Lê um caractere de um arquivofseek() Posiciona em um registro de um arquivofprintf() Efetua impressão formatada em um arquivofscanf() Efetua leitura formatada em um arquivofeof() Verifica o final de um arquivofwrite() Escreve tipos maiores que 1 byte em um arquivofread() Lê tipos maiores que 1 byte de um arquivo

Tabela 1 - Funções do padrão ANSI para manipulação de arquivos

O sistema de entrada e saída do ANSI C é composto por uma série de funções, cujos protótipos estão reunidos em stdio.h . Todas estas funções trabalham com o conceito de "ponteiro de arquivo". Este não é um tipo propriamente dito, mas uma definição usando o comando typedef. Esta definição também está no arquivo stdio.h. Podemos declarar um ponteiro de arquivo da seguinte maneira:

Pela declaração anterior, passa a existir uma variável de nome Arquivo, que é ponteiro para um arquivo. O ponteiro de arquivo une o sistema de E/S a um buffer. O ponteiro não aponta diretamente para o arquivo em disco, mas contém informações sobre o arquivo, incluindo nome, status (aberto, fechado e outros) e posição atual sobre o arquivo.

1

FILE *Arquivo;

Page 2: Arquivos Em C

1) ABRINDO UM ARQUIVO

A função que abre um arquivo em C é a função fopen(), que devolve o valor NULL (nulo) ou um ponteiro associado ao arquivo, devendo ser passado para função o nome físico do arquivo e o modo como este arquivo deve ser aberto.

Com a instrução acima, está sendo aberto um arquivo de nome "texto.txt", no disco, habilitado apenas para escrita (w-write). Utilizando-se técnicas de verificação, pode-se codificar a instrução acima da seguinte maneira:

Além do modo de escrita, a linguagem C permite o uso de alguns valores padronizados para o modo de manipulação de arquivos, conforme mostra a Tabela 2

Modo Significado

"r" Abre um arquivo texto para leitura. O arquivo deve existir antes de ser aberto.

"w"Abrir um arquivo texto para gravação. Se o arquivo não existir, ele será criado. Se já existir, o conteúdo anterior será destruído.

"a"Abrir um arquivo texto para gravação. Os dados serão adicionados no fim do arquivo ("append"), se ele já existir, ou um novo arquivo será criado, no caso de arquivo não existente anteriormente.

"rb" Abre um arquivo binário para leitura. Igual ao modo "r" anterior, só que o arquivo é binário.

"wb" Cria um arquivo binário para escrita, como no modo "w" anterior, só que o arquivo é binário.

"ab" Acrescenta dados binários no fim do arquivo, como no modo "a" anterior, só que o arquivo é binário.

"r+" Abre um arquivo texto para leitura e gravação. O arquivo deve existir e pode ser modificado.

"w+"Cria um arquivo texto para leitura e gravação. Se o arquivo existir, o conteúdo anterior será destruído. Se não existir, será criado.

"a+"Abre um arquivo texto para gravação e leitura. Os dados serão adicionados no fim do arquivo se ele já existir, ou um novo arquivo será criado, no caso de arquivo não existente anteriormente.

"r+b" Abre um arquivo binário para leitura e escrita. O mesmo que "r+" acima, só que o arquivo é binário.

"w+b" Cria um arquivo binário para leitura e escrita. O mesmo que "w+" acima, só que o arquivo é binário.

"a+b"Acrescenta dados ou cria uma arquivo binário para leitura e escrita. O mesmo que "a+" acima, só que o arquivo é binário

Tabela 2 - Modos para manipulação de arquivos

MODO BINÁRIO X MODO TEXTO

Em modo texto, cada caracter (digito, letra, ou caracter especial) ocupa um byte. Ou seja, para gravar o número 32153, que em memória ocuparia 2 bytes, em arquivo modo texto são necessários 5 bytes. O modo binário é mais eficiente para guardar números pois ocupa menos espaço.

2) FECHANDO UM ARQUIVO

Para o esvaziamento do buffer de um arquivo é utilizada a função fclose(), que associa-se diretamente ao nome lógico do arquivo (STREAM).

2

Arquivo = fopen ("texto.txt","w");

if ((Arquivo = fopen("texto.txt","w")) == NULL) { printf("\n Arquivo TEXTO.TXT não pode ser aberto : TECLE ALGO"); getch(); }

fclose (Arquivo);

Page 3: Arquivos Em C

3) GRAVANDO DADOS DADOS EM ARQUIVOS:

Existem várias funções em C para a operação de gravação de dados em Arquivos. Vejamos Algumas :a) putc ou fputc : Grava um único caracter no arquivob) fprintf : Grava dados formatados no arquivo, de acordo com o tipo de dados (float, int, ...). Similar

ao printf, porém ao invés de imprimir na tela, grava em arquivoc) fwrite : Grava um conjunto de dados heterogêneos (struct) no arquivo.

SINTAXE DO PUTC:

putc (caracter, arquivo); /* Grava o conteúdo da variável caracter no "arquivo" */

Vejamos o exemplo de putc, num programa que simula um editor de texto, bem simples, que grava em arquivo um texto que vai sendo digitado via teclado até que o usuário finalize com um CTRL+Z

#include <stdio.h>#include <conio.h>void main () { FILE *Arquivo; char Caractere, Nome[20]; clrscr(); printf("Nome do arquivo? "); fflush(stdin); gets(Nome); Arquivo = fopen (Nome,"w"); if (Arquivo == NULL) { printf ("Erro abertura do Arquivo : %s. Tecle algo !\n",Nome); getch(); } else { do { Caractere = getche(); if (Caractere == 13) { \* teclou enter *\ putc('\n',Arquivo); \* grava um \n no arquivo printf("\n"); \* pular linha na tela pois getche não faz isso com enter */ } else { putc(Caractere,Arquivo); } } while (Caractere != 26); // CTRL + Z para encerrar } fclose(Arquivo); printf("\n Fim da digitação do texto !" ); getch();}

Programa 1 – Manipulação de arquivo-texto para escrita

OBS : Mais adiante veremos a sintaxe e o exemplo de uso de fprintf e fwrite

3

Page 4: Arquivos Em C

4) LENDO DADOS EM ARQUIVOS:

Existem várias funções em C para a operação de leitura de dados de Arquivos. Vejamos Algumas :a) getc ou fgetc : Lê um único caracter do arquivob) fscanf : Lê dados formatados no arquivo, de acordo com o tipo de dados (float, int, ...). Similar

ao scanf, porém ao invés de ler do "teclado" lê de um arquivoc) fread : Lê um conjunto de dados heterogêneos (struct) do arquivo.

SINTAXE DO GETC:

Caracter = getc (arquivo); /* Lê um caracter do "arquivo" e retorna para a variável Caracter */

getc retorna EOF caso encontre o fim-de-arquivo ou em caso de erro na leitura

Vejamos o exemplo de getc, num programa que simula um "mostrador" de texto, bem simples, que lê arquivo texto já gravado em disco e vai mostrando na tela :

#include <stdio.h>#include <conio.h>void main () { FILE *Arquivo; char Nome[20]; char Caractere; clrscr (); printf ("Nome do arquivo? "); fflush(stdin); gets (Nome);

Arquivo = fopen (Nome,"r"); if (Arquivo == NULL) { printf ("Erro abertura do Arquivo : %s. Tecle algo !\n",Nome); getch(); } else { Caractere = getc(Arquivo); while (Caractere != EOF) { printf("%c", Caractere); Caractere = getc(Arquivo); } fclose (Arquivo); printf("\n *** fim de texto *** Tecle algo !"); getch (); }

}Programa 2 – Manipulação de arquivo-texto para leitura

OBS : Mais adiante veremos a sintaxe e o exemplo de uso de fscanf e fread

EXERCICIOS :

a) Escreva um programa que faça a cópia de um arquivo origem, gerando um para um arquivo destino onde todos os caracteres estejam em minúsculo. A função tolower converte um caracter para minúsculo, está na biblioteca ctype.h e possui a seguinte sintaxe :

a = tolower(b); A instrução acima converte o caracter da variável b para minúsculo e retorna para a variável a, onde a e b podem ser a mesma variável.

4

Page 5: Arquivos Em C

b) Escreva um programa para contar quantas palavras existem num arquivo texto. Lembre-se de considerar como separador de palavra os caracteres :

'\t' - caracter de tabulação'\n' – quebra de linha' ' - espaço em branco

AS OUTRAS FUNÇÕES DE LEITURA E GRAVAÇÃO EM ARQUIVO

A) LENDO E GRAVANDO DADOS "FORMATADOS" com fscanf e fprintf

Sintaxe :

int fprintf(arquivo, "formatos", var1, var2 ...);

fprintf retorna a quantidade de bytes gravadas ou EOF em caso de erro

No exemplo abaixo, suponha que arqfunc foi aberto com fopen ... ... FILE *arqfunc; int idade = 21, tot_bytes; char sexo = 'M'; float salario = 552.75; ... tot_bytes = fprintf (arqfunc, "%d %c %f ", idade, sexo, salario);

obs. : Os formatos devem ser separados por espaços em branco

int fscanf(arquivo, "formatos", &var1, &var2 ...);

fscanf retorna a quantidade variáveis lidas com sucesso

No exemplo abaixo, suponha que arqfunc foi aberto com fopen ... ... FILE *arqfunc; int idade = 21, totbytes; char sexo = 'M'; float salario = 552.75; ...quant_var = fscanf (arqfunc, "%d %c %f ", &idade, &sexo, *salario);

obs. : Os formatos devem ser separados por espaços em branco

OBS : O uso de fscanf não é recomendada para string pois, da mesma forma que scanf com %s, fscanf também encerra e leitura ao encontrar um espaço em branco. Em outras palavras, se no arquivo estiver gravado um nome "JOSE DA SILVA SOUZA" o fscanf lerá apenas para o formato %s a palavra "JOSE". Como alternativa poderíamos usar a função fgets, mas esta

5

Page 6: Arquivos Em C

exige que se saiba a quantidade de caracteres a ser lido a cada momento. Resolveremos este problema com fread e fwrite.

De qualquer forma, vejamos exemplos de programas com o uso de fprintf e fscanf

O programa abaixo, obtém o Código do Funcionário, o sexo, a idade e o salário de N pessoas, a partir do teclado, e grava os dados num arquivo, utilizando fprintf

O Critério de terminação é quando o usuário digita um código do funcionário negativo

Por questões de simplificação não estamos verificando se o arquivo foi aberto com sucesso, nem se o sexo é válido ou não ...

/* programa exemplo com fprintf */

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

void main() { FILE *arqfunc; int sexo; int codfunc, idade; float salario;

arqfunc = fopen("FUNCIONA.DAD", "w");

if (arqfunc == NULL) {printf("\nArquivo FUNCIONA.DAD nao pode ser criado.");printf("\nErro Grave ! Tecle algo !");getch();

} else { clrscr(); do {

printf("\n Digite o codigo do funcionario ou um numero negativo \ para encerrar : ");

scanf("%d", &codfunc); if (codfunc > 0){ printf("\n Digite o sexo [M ou F] : "); sexo = getche();

printf("\n Digite a idade : "); scanf("%d", &idade); printf("\n Digite o salario : "); scanf("%f", &salario); /* a instrucao abaixo grava os dados no arquivo */ fprintf(arqfunc, "%d %c %d %f ", codfunc, sexo, idade, salario); }

} while ( codfunc > 0); fclose (arqfunc); }}

O programa abaixo lê o arquivo gravado com o programa anterior, utilizando fscanf e mostra os dados na tela

6

Page 7: Arquivos Em C

Veja que deve-se usar a mesma seqüência de leitura que se usou para gravar : O Primeiro nome, depois o sexo, a idade e o salário.

Veja ainda que o nome é lido com fgets devido ao problema já exposto anteriormente sobre o fscanf com %s

7

Page 8: Arquivos Em C

/* programa exemplo com fscanf

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

#define LETRAS 60

void main() { FILE *arqfunc; char sexo, aux; int codfunc, idade, i = 0; float salario;

clrscr(); arqfunc = fopen("FUNCIONA.DAD", "r");

if (arqfunc == NULL) {printf("\nArquivo FUNCIONA.DAD nao pode ser aberto.");printf("\nErro Grave ! Tecle algo !");getch();

} else { aux = fscanf(arqfunc, "%d %c %d %f",&codfunc, &sexo, &idade, &salario); while (aux != EOF) {

i = i + 1; printf("\n Dados do %d § funcionario : \n ", i); printf("\n Codigo : %d Sexo : %c", codfunc, sexo); printf("\n Idade ...: %d Salario : %8.2f", idade, salario); printf("\n------------------------------------- Tecle algo !"); getch(); aux = fscanf(arqfunc, "%d %c %d %f",&codfunc, &sexo, &idade, &salario);

}

fclose (arqfunc); printf("\n *** FIM : Tecle algo ! "); getch(); }}

B) LENDO E GRAVANDO ESTRUTURAS

Além da manipulação de arquivos do tipo texto, pode-se ler e escrever estruturas maiores que 1 byte, usando as funções fread() e fwrite(), conforme os protótipos seguintes.

O buffer é um endereço de memória da estrutura de onde deve ser lido ou onde devem ser escritos os valores (fread() e fwrite(), respectivamente). O tamanhoembytes é um valor numérico que define o número de bytes da estrutura que deve ser lida/escrita. A quantidade é o número de estruturas que devem ser lidas ou escritas em cada processo de fread ou fwrite. O ponteirodearquivo é o ponteiro do arquivo de onde deve ser lida ou escrita uma estrutura.

Normalmente quando trabalhos com arquivos (não texto), utilizamos arquivos de estruturas (struct). Podemos por exemplo falar num arquivo de CLIENTES, onde cada cliente possui NOME, RG, ENDERECO E TELEFONE.

8

fread (buffer, tamanhoembytes, quantidade, ponteirodearquivo) fwrite (buffer, tamanhoembytes, quantidade, ponteirodearquivo)

Page 9: Arquivos Em C

Na linguagem de ARQUIVOS, cada OCORRÊNCIA de cliente num arquivo é chamado de REGISTRO e cada informação dentro do REGISTRO do cliente é chamada de CAMPO.

Num arquivo com 10 clientes, dizemos que há 10 registros. No exemplo acima, dizemos que os campos do REGISTRO de Clientes são : NOME, RG, ENDEREÇO e TELEFONE.

OBS. : A função sizeof retorna a quantidade de bytes de um determinado tipo ou variável

Exemplo :

sizeof(int) retorna 2 de acordo com o tipo de máquinasizeof(struct cliente) retorna a somatória de bytes da struct cliente

Exemplos :

O PROGRAMA ABAIXO CRIA UM ARQUIVO E GRAVA OS DADOS NESTE ARQUIVO

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

#define LETRAS 50struct Tcliente { char situacao; // situacao do registro : excluido ou nao ? int codigo; // codigo do sujeito char nomecli[LETRAS]; // nome do sujeito char fone [15]; // fone do sujeito char sexo; // sexo float limite; // limite de credito};

// prototiposvoid Entrada (FILE *);char ValidaSexo();char Validaresp();

// =================================================================void main() { FILE *cliente; char verro = 'N'; char arqcli [] = {"CLIENTE.DAD"};

cliente = fopen(arqcli, "rb+"); if (cliente == NULL) { printf(" \n Arquivo %s Nao existe : Tecle algo para criar agora ! ", arqcli); getch();

if ((cliente = fopen(arqcli, "wb+")) == NULL) { verro = 'S'; printf(" \n Erro grave ! Nao consigo criar o arquivo %s !!!", arqcli); getch();

} }

if (verro == 'N') { Entrada(cliente); fclose (cliente);

}

9

Page 10: Arquivos Em C

}

// entrada de dados gravando direto em arquivovoid Entrada (FILE * cliente) { int retorno; struct Tcliente Vcli; char vresp;

do { clrscr(); printf("\n Digite o Codigo [Zero encerra] : " ); scanf("%d", &Vcli.codigo); if (Vcli.codigo != 0) {

printf(" \n Digite o nome : "); fflush(stdin); gets(Vcli.nomecli); Vcli.sexo = ValidaSexo(); printf(" \n Digite o Fone : " ); gets(Vcli.fone); printf(" \n Digite o Limite de Credito do cliente : "); scanf("%f", &Vcli.limite); vresp = Validaresp(); if (vresp == 'S') { retorno = fwrite (&Vcli, sizeof(struct Tcliente) ,1,cliente); // fwrite retorna a quantidade de itens gravados (NAO BYTES) if (retorno == 1) { printf(" \n Gravacao ok ! "); getch(); } else { printf (" \n Problemas : Gravacao nao efetuada !!!" ); getch(); } }

} } while (Vcli.codigo != 0);}// validar o sexochar ValidaSexo() { char vsexo; do { printf(" \n Digite o Sexo [M ou F] : " ); vsexo = getche(); } while (vsexo != 'F' && vsexo != 'M'); return vsexo;}

// validar a respostar// validar o sexochar Validaresp() { char vresp; do { printf(" \n Confirma Inclusao [S ou N] ? " ); vresp = getche(); } while (vresp != 'S' && vresp != 'N'); return vresp;}

10

Page 11: Arquivos Em C

O PROGRAMA ABAIXO ABRE UM ARQUIVO E IMPRIME OS DADOS NA TELA

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

#define LETRAS 50struct Tcliente { char situacao; // situacao do registro : excluido ou nao ? int codigo; // codigo do sujeito char nomecli[LETRAS]; // nome do sujeito char fone [15]; // fone do sujeito char sexo; // sexo float limite; // limite de credito};

// prototiposvoid Le_Imprime (FILE *);

void main() { FILE *cliente; char verro = 'N'; char arqcli [] = {"CLIENTE.DAD"};

if ((cliente = fopen(arqcli, "rb")) == NULL) { verro = 'S'; printf(" \n Erro Grave : Arquivo Nao existe !"); getch();

}

if (verro == 'N') {

Le_Imprime(cliente);

fclose (cliente); }

}

// Le dados de um arquivo e imprime na Telavoid Le_Imprime (FILE * cliente) { int retorno, cont = 0; struct Tcliente Vcli;

retorno = fread(&Vcli, sizeof(struct Tcliente), 1, cliente); // fread retorna a quantidade de itens retornados ... clrscr(); while ( retorno == 1) { cont++; printf("\n\n DADOS DO CLIENTE %d \n", cont); printf("\n Codigo : %d", Vcli.codigo); printf("\n Nome ..: %s", Vcli.nomecli); printf("\n Sexo ..: %c", Vcli.sexo); printf("\n Fone ..: %s", Vcli.fone); printf("\n Limite : %.2f", Vcli.limite); retorno = fread(&Vcli, sizeof(struct Tcliente), 1, cliente);

} printf(" \n\n %d clientes cadastrados ", cont); getch();}

11