Linguagem de Programação Estruturada Prof. Leandro Carlos Fernandes
2º semestre 2015
Entrada e Saída de Dados
•
Em C não existem comandos de Entrada e Saída, sendo estas tarefas executadas por funções especialmente criadas para esta finalidade e armazenadas em bibliotecas específicas.
•
Para manipular os vários tipos de dispositivos de armazenamento e seus diferentes formatos a linguagem C utiliza o conceito de fluxo
(stream) de dados.
Entrada e Saída de Dados
•
Todos os sistemas de arquivos se comportam da mesma maneira quando manipulados como um fluxo contínuo de dados.
•
Dados podem ser manipulados em dois diferentes tipos de fluxos:
–fluxos de texto e;
–fluxos binários.
Fluxos (streams)
• Fluxo de texto:composto por uma seqüência de caracteres, que pode ou não ser dividida em linhas terminadas por um caractere de final de linha.
–Um detalhe que deve ser considerado é que na última linha não é obrigatório o caractere de fim de linha.
• Fluxo binário:composto por uma seqüência de bytes lidos, sem tradução, diretamente do dispositivo externo.
–Não ocorre nenhuma tradução e existe uma correspondência um para um entre os dados do dispositivo e os que estão no fluxo.
Arquivos
• Os arquivos são entendidos como streamscujos dados estão guardados em um dispositivo de armazenamento secundário
• Operações comuns em arquivos são:
– abertura e fechamento de arquivos;
– apagar um arquivo;
– leitura e escrita de um caractere;
– indicação de que o fim do arquivo foi atingido;
– posicionar o arquivo em um ponto determinado
• Importante:
– Ao final das operações necessárias o programa deve fechar o arquivo.
– Quando um programa é encerrado todos os arquivos associados são fechados automaticamente e os conteúdos dos buffers são descarregados para o dispositivo externo.
Funções da biblioteca stdio.h
Função Descrição
fopen() Abre um arquivo
putc(), fputc() Escreve um caractere em um arquivo getc(), fgetc() Lê um caractere de um arquivo fprintf() Equivalente a printf(), usando stream sscanf() Equivalente a scanf(), usando string fscanf() Equivalente a scanf(), usando stream fseek() Posiciona o arquivo em um ponto específico rewind() Posiciona o arquivo no início
feof() Retorna VERDADE se chegou ao fim do arquivo ferror() Verifica a ocorrência de erro
fflush() Descarrega o buffer associado com o arquivo fwrite() Escrita de dados no modo binário
fread() Leitura de dados no modo binário
Referenciando um arquivo
• Para ter acesso aos dados em um arquivo é necessário a definição de um ponteiro do tipo especial FILE, definido na biblioteca stdio.h.
• Um ponteiro deste tipo permite que o programa tenha acesso a uma estrutura que armazena informações importantes sobre o arquivo. Para definir uma variável deste tipo o programa deve conter a seguinte
declaração
FILE *arq;
onde arqé o ponteiro que será usado para executar as operações no arquivo.
Abrindo um arquivo
• Antes de qualquer operação ser executada com o arquivo, ele deve ser aberto. Esta operação associa um fluxo de dados a um arquivo.
Um arquivo pode ser aberto de diversas maneiras: leitura, escrita, leitura/escrita, adicão de texto, etc.
• A função utilizada para abrir o arquivo é chamada fopen() e tem o seguinte protótipo:
FILE*fopen (const char *parq, const char *modo) nela, parqdeve ser uma string que identifique o nome do arquivo ("drive:\\path\\nome_do_arquivo"); e modo é uma string que define a maneira como o arquivo vai ser aberto.
– Este ponteiro não deve ser modificado e a função retorna um ponteiro nulo (NULL) se o arquivo não puder ser aberto.
Exemplo: Abrindo um arquivo
• A maneira mais comum de abrir um arquivo está ilustrado no exemplo abaixo:
FILE *pa;
pa = fopen("arquivo.txt","w") if(pa == NULL) {
printf("O arquivo não pode ser aberto.");
exit(1);
}
Modos de Abertura
/* 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.
Modos de Abertura
/* Modo: Significado */
• “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 poder 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.
Modos de Abertura
/* Modo: Significado */
• “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
Fechando um arquivo
• Um arquivo aberto por meio da função fopen() deve ser fechado com a função fclose() cujo protótipo é:
intfclose(FILE *parq);
onde parqé um ponteiro de arquivo para o arquivo que deve ser fechado.
– Um valor zero de retorno significa que a operação foi executada com êxito, qualquer outro valor implica em erro.
– A operação fclose() implica em escrita no arquivo de qualquer dado que ainda não tenha sido escrito.
Checando se é o fim do arquivo
• A função feof() indica que um arquivo chegou ao seu final e o protótipo da função é o seguinte:
intfeof(FILE *parq)
– A pergunta que pode surgir é a seguinte - Se já existe o valor EOF para indicar o final de arquivo por que precisamos de uma função extra do tipo feof()?
• O problema é que EOF é um valor inteiro e ao ler arquivos binários este valor pode ser lido como parte do arquivo e não por ser o final do arquivo. A função feof() serve para indicar que o final de um arquivo binário foi encontrado.
– Naturalmente esta função pode ser aplicada também a arquivos texto.
Posicionando no início
• A função rewind() recoloca o indicador de posição de arquivo no inicio do arquivo. Uma operação
semelhante ao que fazemos em uma fita cassete de música ou vídeo. O protótipo da função é o seguinte:
voidrewind(FILE *parq)
– É importante observar que o arquivo deve estar aberto em um modo que permita a execução das operações
desejadas. Por exemplo, um arquivo aberto somente para escrita e em seguida rebobinado para o início, não irá permitir outra operação que não seja escrita.
Exemplo: Arquivo caractere à caractere
#include <stdio.h>
#include <stdlib.h>
intmain () { intc;
FILE *pa;
charnome[] = "texto.txt";
/* Abre o arquivo para leitura e escrita */
if (( pa = fopen(nome, "w+")) == NULL) {
printf("\n\nNão foi possível abrir o arquivo .\n");
exit(1);
}
Exemplo: Arquivo caractere à caractere
/* Cada caractere digitado será gravado no arquivo */
c = getchar();
while(!feof(stdin)) { /* Quando digitado CTRL+Z */
fputc(c, pa); /* grava c no arquivo pa e */
c = getchar(); /* ...lê o próximo caractere */
}
rewind(pa); /* volta ao inicio do arquivo */
printf("\nTerminei de escrever, agora vou ler.\n");
Exemplo: Arquivo caractere à caractere
/* Cada caractere lido do arquivo será escrito na tela*/
c = fgetc(pa);
while(!feof(pa)) { /* enqto não acabar o arquivo: */
putchar(c); /* escreve o caractere e */
c = fgetc(pa); /* ...coleta o próximo.*/
}
fclose(pa); /* fecha o arquivo */
return0;
}
Exemplo: Arquivo como strings
#include <stdio.h>
#include <stdlib.h>
#define MAX 80 intmain () {
intc;
FILE *pa;
charnome[] = "texto.txt", linha[MAX];
/* Abre o arquivo para leitura e escrita */
if (( pa = fopen(nome, "w+")) == NULL) {
printf("\n\nNão foi possível abrir o arquivo .\n");
exit(1);
}
Exemplo: Arquivo como strings
/* Cada caractere digitado será gravado no arquivo */
gets(linha);
while(!feof(stdin)) { /* Quando digitado CTRL+Z */
strcat(linha,"\n");
fputs(linha, pa); /* grava a linha no arquivo / gets(linha); /* ...lê o próximo caractere */
}
rewind(pa); /* volta ao inicio do arquivo */
printf("\nTerminei de escrever, agora vou ler.\n");
Exemplo: Arquivo como strings
/* Cada linha do arquivo será escrito na tela*/
fgets(linha, MAX, pa);
while(!feof(pa)) { /* enqto não acabar o arquivo: */
printf(“%s”, linha); /* escreve o caractere e */
fgets(linha, MAX, pa); /* ...coleta o próximo.*/
}
fclose(pa); /* fecha o arquivo */
return0;
}
Exemplo: Arquivo Binário
#include<stdio.h>
#include<stdlib.h>
#define MAX 4 structpessoa {
charnome[40];
intano;
};
intmain () { FILE *pa;
charnome[40]; inti;
structpessoa turma [MAX], back[MAX];
Exemplo: Arquivo Binário
/* Coleta as informações de cada aluno da turma, armazenando num vetor em que cada posição representa um aluno */
for (i=0; i<MAX; i++) {
printf("Nome.: "); scanf("%s",&turma[i].nome);
printf("Ano..: "); scanf("%d",&turma[i].ano);
}
/* Exibe a lista na tela */
puts ("\nImprimindo\n");
for(i=0; i<MAX; i++) {
printf("Nome.: %s\n", turma[i].nome);
printf("Ano..: %d\n", turma[i].ano);
printf("---\n");
}
Exemplo: Arquivo Binário
/* Solicita o nome do arquivo a ser grava */
puts("\nGravando\n");
puts("Qual o nome do arquivo?");
gets(nome);
/* Tenta criar o arquivo com o nome dado pelo usuário */
if(( pa = fopen(nome, "w+b")) == NULL ) { puts("Arquivo nao pode ser aberto");
exit(1);
}
/* Grava cada um dos registros do vetor no arquivo */
for(i=0; i<MAX; i++) {
if(fwrite( &turma[i], sizeof(structpessoa), 1, pa) != 1) puts("Erro ao tentar escrever dados no arquivo.");
}
Exemplo: Arquivo Binário
/* Posiciona o arquivo no início */
rewind(pa);
/* Lê o conteúdo do arquivo e carrega o vetor back */
for(i=0; i<MAX; i++) {
if(fread( &back[i], sizeof(structpessoa), 1, pa) != 1) puts("Erro na leitura.");
if(feof(pa)) break;
}
/* Imprime o conteúdo recuperado do arquivo na tela */
puts("Imprimindo o vetor lido.");
for(i=0; i<MAX; i++) {
printf("Nome = %s\n", back[i].nome);
printf("Ano = %d\n\n", back[i].ano);
} exit(0);
}