Baixe o app para aproveitar ainda mais
Prévia do material em texto
A23: Arquivos binários (1). Acesso sequencial Kazuki Yokoyama kmyokoyama@inf.ufrgs.br Algoritmos e Programação INF01202 – Algoritmos e Programação, 2018/01, Turmas I e J *adaptado do material do prof. Marcelo Walter e prof. Rodrigo Ruas Oliveira e cedido pela profª. Mariana Recamonde Atenção: O material aqui contido não substitui a leitura do livro texto e é incompleto sem a apresentação do professor em aula. 2 Estruturas: prototipação, declaração e manipulação Estruturas e funções: retorno e parâmetro por valor Semana passada struct nome_estrutura funcao() { struct nome_estrutura var; (...) return var; } void funcao(struct nome_estrutura par) { int x = par.campo1; par.campo2 = …; (...) } 3 struct et_st { float altura, peso; char nome[30]; int n_olhos, n_dedos; (...) }; Semana passada 4 Typedef typedef struct ponto_st { int x; int y; } ponto_t; int main() { ponto_t p1, p2, *ptr_ponto; ptr_ponto = &p1; (... } Ponteiros, estruturas e funções: Parâmetros por referência void le_ponto(ponto* pnt) { printf("\nCoordenadas do Ponto: "); scanf("%f %f", &pnt->x, &pnt->y); // ou scanf("%f %f", &(*pnt).x, &(*pnt).y); } void le_dados_alunos(aluno_st* alunos, int tam) { int i, j; for (j=0; j < tam; j++) { printf ( "\nALUNO %d. Nome: ",j+1); fgets(alunos[j].nome, 15, stdin); alunos[j].media = 0; printf(“Digite as %d notas: ”, NRNOTAS); for (i = 0; i < NRNOTAS ; i++) { scanf(“%f”, &alunos[j].nota[i]); while (alunos[j].nota[i] < 0 || alunos[j].nota[i]> 10) { printf(“Nota invalida\n”); scanf(“%f”, &alunos[j].nota[i]); } alunos[j].media += alunos[j].nota[i]; } alunos[j].media = alunos[j].media/NRNOTAS; (...) } } //continua… //chamada à funcao (na main): aluno_st listaAlunos[NALUNOS]; le_dados_aluno(listaAlunos, NALUNOS); Vetor de estruturas passado para funções por referência Exercício 1. Defina em C um novo tipo denominado Passagem, conforme layout do bilhete de passagem de ônibus mostrado ao lado. Os campos data e horário são estruturas que possuem, respectivamente, 3 e 2 campos. 5 2. A partir da estrutura definida no item 1, implemente as funções ler_bilhete e mostrar_bilhete, que permitem, respectivamente, ler e mostrar todos os dados relativos a um determinado bilhete. A função ler_bilhete poderia ser implementada através de uma função sem parâmetros que retorna um struct, ou através de uma função void (ou seja, sem retorno) que recebe o struct como parâmetro por referência. Tente implementar e testar os dois casos para praticar! 3. Na main(), declare um vetor de estruturas tipo Passagem, que irá armazenar todos os Bilhetes vendidos em um determinado período pela Viação Viaje Bem (assuma um máximo de 200 bilhetes). Leia e posteriormente imprima as informações de N passagens usando as funções declaradas, onde N será informado pelo usuário e deve ser validado (N < 200). 4. Por fim, faça uma função que receba o vetor de estruturas tipo Passagem, o número de passagens vendidas (N) e imprima na tela os dados de todas as passagens vendidas em um determinado mês, também informado como parâmetro da função (por exemplo, “Janeiro”, ‘J’ ou 0). Teste a chamada desta função na main(). Exercício 1. Defina em C um novo tipo denominado Passagem, conforme layout do bilhete de passagem de ônibus mostrado ao lado. Os campos data e horário são estruturas que possuem, respectivamente, 3 e 2 campos. 6 // Definicoes necessarias #include <stdio.h> #include <string.h> #define MAX 31 typedef struct data { int dia, mes, ano; } Data_st; typedef struct horario { int hora, min; } Horario_st; typedef struct passagem { int cod; char nome[MAX], destino[MAX], origem[MAX]; Data_st data; Horario_st horario; int assento; float valor; } Passagem_st; //continua... 2. A partir da estrutura definida no item 1, implemente as funções ler_bilhete e mostrar_bilhete, que permitem, respectivamente, ler e mostrar todos os dados relativos a um determinado bilhete. A função ler_bilhete poderia ser implementada através de uma função sem parâmetros que retorna um struct, ou através de uma função void (ou seja, sem retorno) que recebe o struct como parâmetro por referência. Tente implementar e testar os dois casos para praticar! 7 void ler_bilhete (Passagem_st* bilhete) { printf("Codigo: "); scanf("%d", &bilhete->cod); printf("Data (dia mes ano): "); scanf("%d %d %d", &bilhete->data.dia,&bilhete->data.mes,&bilhete->data.ano); printf("Horario (hora minutos): "); scanf("%d %d", &bilhete->horario.hora,&bilhete->horario.min); printf("Nome do passageiro: "); fflush(stdin); fgets(bilhete->nome,MAX-1,stdin); printf("Origem: "); fflush(stdin); fgets(bilhete->origem,MAX-1,stdin); printf("Destino: "); fflush(stdin); fgets(bilhete->destino,MAX-1,stdin); printf("Assento: "); scanf("%d", &bilhete->assento); printf("Valor: "); scanf("%f", &bilhete->valor); } //continua... 2. A partir da estrutura definida no item 1, implemente as funções ler_bilhete e mostrar_bilhete, que permitem, respectivamente, ler e mostrar todos os dados relativos a um determinado bilhete. A função ler_bilhete poderia ser implementada através de uma função sem parâmetros que retorna um struct, ou através de uma função void (ou seja, sem retorno) que recebe o struct como parâmetro por referência. Tente implementar e testar os dois casos para praticar! 8 void mostrar_bilhete (Passagem_st bilhete) { printf("Codigo: %d\n", bilhete.cod); printf("Data: %2d/%2d/%4d\n",bilhete.data.dia,bilhete.data.mes,bilhete.data.ano); printf("Horario: %2d:%2d\n",bilhete.horario.hora,bilhete.horario.min); printf("Nome Passageiro: %s\n", bilhete.nome); printf("Origem: %s\n", bilhete.origem); printf("Destino: %s\n", bilhete.destino); printf("Valor: R$ %.2f\n", bilhete.valor); } //continua... 3. Na main(), declare um vetor de estruturas tipo Passagem, que irá armazenar todos os Bilhetes vendidos em um determinado período pela Viação Viaje Bem (assuma um máximo de 200 bilhetes). Leia e posteriormente imprima as informações de N passagens usando as funções declaradas, onde N será informado pelo usuário e deve ser validado (N < 200). 9 int main() { Passagem_st novobilhete[200]; int i,n; do{ printf("Numero de passagens a processar? "); scanf("%d",&n); if (n < 0 || n > 200) printf(“Valor invalido!\n”); } while(n < 0 || n > 200); for(i=0; i<n ; i++) ler_bilhete(&novobilhete[i]); for(i=0; i<n ; i++) mostrar_bilhete(novobilhete[i]); return 0; } 4. Por fim, faça uma função que receba o vetor de estruturas tipo Passagem, o número de passagens vendidas (N) e imprima na tela os dados de todas as passagens vendidas em um determinado mês, também informado como parâmetro da função (por exemplo, “Janeiro”, ‘J’ ou 0). Teste a chamada desta função na main(). 10 void vendas_no_mes(Passagem_st* bilhetes, int tam, int mes) { int i, cont=0; printf("Vendas no mes: %d\n",mes); for (i=0; i< tam; i++){ if (bilhetes[i].data.mes == mes) { cont++; printf("---Registro encontrado---\n"); printf("Codigo: %d\n", bilhetes[i].cod); printf("Data: %2d/%2d/%4d\n",bilhetes[i].data.dia,bilhetes[i].data.mes,bilhetes[i].data.ano); printf("Horario: %2d:%2d\n",bilhetes[i].horario.hora,bilhetes[i].horario.min); printf("Nome Passageiro: %s\n", bilhetes[i].nome); printf("Origem: %s\n", bilhetes[i].origem); printf("Destino: %s\n", bilhetes[i].destino); printf("Valor: R$ %.2f\n\n", bilhetes[i].valor); } } if (cont==0) printf("Nenhum registro encontrado!\n"); } 4. Por fim, faça uma função que receba o vetor de estruturas tipo Passagem, o número de passagens vendidas (N) e imprima na tela os dados de todas as passagens vendidas em um determinado mês, também informado como parâmetro da função (por exemplo, “Janeiro”, ‘J’ ou 0).Teste a chamada desta função na main(). 11 int main() { Passagem_st novobilhete[200]; int i,n; do{ printf("Numero de passagens a processar? "); scanf("%d",&n); if (n < 0 || n > 200) printf(“Valor invalido!\n”); } while(n < 0 || n > 200); for(i=0; i<n ; i++) ler_bilhete(&novobilhete[i]); for(i=0; i<n ; i++) mostrar_bilhete(novobilhete[i]); vendas_no_mes(novobilhete, n, 03); return 0; } Arquivos Binários (1), acesso sequencial 12 Repositórios permanentes de dados (informações) que possibilitam a comunicação dos programas com o ambiente. Usualmente armazenados em dispositivos de memória auxiliar (discos). A alteração de um arquivo durante a execução de um programa possibilita salvar o processamento realizado, tornando-o permanente (além do tempo de execução do programa). Em arquivos é possível armazenar bem mais informações do que na memória principal. Arquivos 13 int bufferInt[10]; char bufferchar[10]; Stream (fluxo): repositórios permanentes de sequências de bytes armazenados em dispositivos de memória permanente, a partir do uso de periféricos (discos, pen drives, etc.) que aceitam tanto a leitura como a gravação de dados. Device independent: toda a entrada ou saída de dados é processada da mesma forma, através do processamento de streams, independentemente do periférico utilizado (discos, pen drives, mouse, teclado, tela etc) Buffers: As operações de entrada e saída de dados de um arquivo (incluídos os dispositivos padrão stdin/stdout) são apoiadas pelo armazenamento temporário destes streams em áreas da memória principal denominadas buffers. Arquivos em C 14 Arquivos: esquema de manipulação Arquivo: entidade externa ao programa Armazenamento permanente ( não se perdem ao término do programa) das informações em memória secundária (periférica) 15 Binário: composto por uma sequência (fluxo binário) de bytes lidos/escritos, sem tradução, diretamente do/no dispositivo externo. Existe uma correspondência um para um entre os dados do dispositivo e os do fluxo. Texto: composto de uma sequência de bytes correspondendo a uma sequência de caracteres ASCII (letras, dígitos e caracteres especiais) utilizados na escrita e separadores (espaço em branco, tab, nova linha..). Dependendo do sistema utilizado (Windows, Linux, ou Mac), a terminação de linha difere: Windows: \r\n; Unix (Linux, BSD, Mac OSX): \n; Mac classic: \r; Tipos de arquivos em C Aula de hoje 16 Arquivos binários Fisicamente: sequência de bits (0's e 1's), armazenada de forma sequencial na unidade de bytes (8 bits). O tamanho é teoricamente ilimitado. 17 Logicamente: o stream pode ser visto como um conjunto de dados simples, ou estruturado, cuja organização depende do programa que utiliza o arquivo. Unidade de manipulação: somente um elemento pode ser acessado de cada vez, em uma posição corrente na stream. O tamanho do elemento corrente depende para cada dispositivo (geralmente 1 byte). Os elementos correntes não têm nome. Acesso aos dados - Sequencial vs. Aleatório: sequencial lê os dados na ordem do stream, enquanto o aleatório seleciona uma posição em qualquer ponto do stream. C: stream vs. arquivo Stream: Conjunto sequencial de bytes, sem qualquer estrutura interna São vistos por programas ou comandos como fluxo de bytes Arquivo: Característica física: stream (fluxo de bytes) Característica lógica: Na memória principal, o buffer pode ser visualizado e manipulado pelo programa como valores simples ou estruturados 18 Arquivos binários: armazenamento 19 No contexto da disciplina, trataremos de arquivos binários que armazenam informações de somente um tipo de dado, seja ele simples (int, char, float) ou estruturado (arranjos ou estruturas) Utilizando arquivos em C A utilização de arquivos em C (binários ou arquivo texto) envolve os seguintes passos: 1 Declaração do arquivo através de um ponteiro (do tipo específico FILE *) FILE *point_arq; 2 Abertura do arquivo, onde o ponteiro declarado é associado fisicamente ao arquivo externo através de um comando específico (fopen) point_arq = fopen(“nome_do_arquivo”, “modo_de_abertura”) 3 Operações com arquivos, através de funções de manipulação de arquivos (leitura, escrita, dentre outras). Todas estas funções são aplicadas ao ponteiro associado ao arquivo. 4 Fechamento do arquivo, através de um comando específico (fclose) fclose(point_arq); 20 Arquivos binários: FILE (declaração) Sintaxe e exemplo: FILE *nome_arquivo; Definição: estrutura que armazena informações de manipulação de arquivos (qual o arquivo, onde ele está, qual a posição atual no arquivo, tamanho, …) Para que um arquivo possa ser usado pelo programa, é necessário que seja declarado através da estrutura FILE, onde cada arquivo a ser usado pelo programa é associado a uma variável do tipo apontador #include <stdio.h> (...) int main() { FILE *arquivo; FILE *times, *pontuacao; (...) } Observar que FILE é sempre escrito em maiúsculas! Para cada arquivo a ser usado simultaneamente no programa, deve haver um ponteiro 21 Arquivos binários: abertura Sintaxe: FILE *nome_var; //declaração nome_var = fopen("nome do arquivo","modo de abertura"); Abre/cria/recria um arquivo para permitir sua manipulação Parâmetros: string nome do arquivo físico (completo ou relativo) string modo de abertura desejado Retorno: ponteiro do tipo FILE com endereço inicial para a estrutura de manipulação deste arquivo OU NULL, se a função não tiver sido bem sucedida Após abertura, verificar SEMPRE se não houve erro! 22 Arquivos binários: modos de abertura Sintaxe: nome_var = fopen("nome do arquivo","modo de abertura"); O modo de abertura define o tipo de acesso que o programa terá sobre o arquivo 23 Arquivos binários: abertura - Exemplo #include <stdio.h> // inclui as funções com arquivos int main( ) { FILE *arq1, *arq2; // declaração de apontadores de arquivo arq1 = fopen("c:\\exemplo1.bin","rb"); // abertura para leitura (caminho completo) if (arq1 == NULL) { // verifica se funcionou: retorno NULL indica erro printf("Erro na abertura do arquivo 1."); } else { // abertura para leitura, junto à análise do resultado da operação: if (!(arq2 = fopen("c:\\exemplo2.dat","rb")) { // not(null) = true printf("Erro na abertura do arquivo 2."); } ... } ... 24 Arquivos binários: abertura - Exemplo #include <stdio.h> // inclui as funções com arquivos int main( ) { FILE *arq1, *arq2; // declaração de apontadores de arquivo arq1 = fopen("c:\\exemplo1.bin","rb"); // abertura para leitura (caminho completo) if (arq1 == NULL) { // verifica se funcionou: retorno NULL indica erro printf("Erro na abertura do arquivo 1."); } else { // abertura para leitura, junto à análise do resultado da operação: if (!(arq2 = fopen("c:\\exemplo2.dat","rb")) { // not(null) = true printf("Erro na abertura do arquivo 2."); } ... } ... 25 Duas maneiras de testar se a abertura do arquivo ocorreu corretamente! Arquivos binários: fechamento Sintaxe: FILE *nome_var; //declaração nome_var = fopen("nome do arquivo","modo de abertura"); (...) fclose(nome_var); //ponteiro do tipo FILE passado como argumento Fecha um arquivo para garantir que dados escritos estão consistentes e liberar sua manipulação por outro programa Parâmetros: ponteiro do tipo FILE com endereço inicial para a estrutura de manipulação deste arquivo Sem retorno. Pode apresentar erro, caso o ponteiro passado seja inválido! 26 Arquivos binários: fechamento - Exemplo 27 #include <stdio.h> // inclui as funções com arquivos int main( ) { FILE arq1; // declaração de apontadores de arquivo arq1 = fopen("exemplo.bin","rb"); // abertura para leitura (caminho relativo) if (!arq1) { // verifica se funcionou:not(null) = true printf("Errona abertura do arquivo exemplo.bin."); } else { // efetua operacoes no arquivo com funcoes de manopulacao … fclose(arq1); // fecha arquivo apos o uso } return 0; } É dever do programador lembrar de fechar corretamente o arquivo para garantir consistência dos dados Utilizando arquivos em C: funções de manipulação A utilização de arquivos em C (binários ou arquivo texto) envolve os seguintes passos: 1 Declaração do arquivo através de um ponteiro (do tipo específico FILE *) FILE *point_arq; 2 Abertura do arquivo, onde o pointeiro declarado é associado fisicamente ao arquivo externo através de um comando específico (fopen) point_arq = fopen(“nome_do_arquivo”, “modo_de_abertura”) 3 Operações com arquivos, através de funções de manipulação de arquivos (leitura, escrita, dentre outras). Todas estas funções são aplicadas ao ponteiro associado ao arquivo. 4 Fechamento do arquivo, através de um comando específico (fclose) fclose(point_arq); 28 Arquivos binários: acesso sequencial Funções de manipulação de arquivos binários 29 Funções de manipulação: fread() 30 Funções de manipulação: fwrite() 31 Funções de manipulação: feof() 32 Ler uma quantidade determinada de números inteiros, e gravar em um arquivo binário. Depois, ler os valores do arquivo e armazenar em um vetor. Exemplo 33 Dica: sizeof( var ) ou sizeof( TIPO ) retorna o tamanho, em bytes, de uma variável ou tipo. Exemplos: int numero; char letra; sizeof( numero ); // retorna 4 (4 bytes) sizeof( int ); // retorna 4 (4 bytes) sizeof( letra ); // retorna 1 (1 byte) sizeof( char ); // retorna 1 (1 byte) // Programa de manipulação de arquivos: escrita e leitura #include <stdio.h> #include <string.h> #define NUMEL 5 int main( ) { FILE *arq; //declaração de um ponteiro para arquivo char nome[16]; int vetor[NUMEL], cont, valor; printf("Digite o nome do arquivo: "); scanf("%s", nome); // ATENÇÃO: não aceita espaços // escrita do vetor // continua... 34 Exemplo // continuando... // escrita: le dados do teclado, elemento a elemento, e vai copiando ao arquivo if(!(arq = fopen(nome,"wb"))) // abre para escrita e testa a abertura printf("Erro na abertura\n"); else { printf("Entre %d valores inteiros\n", NUMEL); for (cont = 0; cont < NUMEL; cont++){ scanf("%d", &valor); // escreve 1 quant de 4 bytes (sizeof valor) e testa escrita if (fwrite(&valor, sizeof(valor), 1, arq) != 1) printf("Erro na escrita!\n"); } fclose(arq); // fecha o arquivo } // leitura do vetor, elemento a elemento // continua... 35 Exemplo // continuando... // leitura: le dados do arquivo, elemento a elemento, e vai armazenando no vetor if(!(arq = fopen(nome,"rb"))) // abre para leitura printf("Erro na abertura\n"); else { for (cont = 0; cont < NUMEL; cont++) { // varre o arquivo // le 1 quant de 4 bytes (sizeof valor) do arquivo e testa leitura if (fread(&vetor[cont], sizeof(valor), 1, arq) == 1) printf("vetor[%d] = %d\n", cont, vetor[cont]); else printf("Erro na leitura!!\n"); } fclose(arq); // fecha o arquivo } return 0; } 36 Exemplo // continuando... // leitura v2: le os dados de uma só vez e copia ao vetor if(!(arq = fopen(nome,"rb"))) // abre para leitura printf("Erro na abertura\n"); else { quant_lida = fread(vetor, sizeof(valor), NUMEL, arq); fclose(arq); } if (quant_lida != NUMEL) // teste da leitura printf("Erro na leitura\n"); else for (cont = 0; cont < NUMEL; cont++) printf("vetor[%d] = %d\n", cont, vetor[cont]); return 0; } 37 Exemplo Indica leitura de informações com o tamanho em bytes de valor multiplicado por NUMEL vezes Funções de manipulação: fflush() 38 Funções de manipulação: rewind() 39 Faça 4 programas diferentes para manipular dados de atletas. 1. Gravar um arquivo composto por estruturas que contenham o seguinte conjunto de dados: nome (até 30 letras), idade e altura. 2. Listar um arquivo com estas estruturas. 3. Exibir a altura de um determinado atleta, cujo nome foi lido do teclado. 4. Adicionar um novo registro no final do arquivo. Arquivos binários: exercício 40 // Programa de manipulação de arquivos // Definicoes necessarias #include <stdio.h> #include <string.h> #define MAX_STRLEN 31 typedef struct atleta_st { char nome[MAX_STRLEN]; int idade; float altura; } atleta_t; Arquivos binários: exercício 41 // Programa 1 int main() { atleta_t buffer; FILE *arq; //declaração do ponteiro para arquivo char nome[STR_MAXLEN]; int op; printf("Nome do arquivo (maximo %d caracteres): ", STR_MAXLEN-1); fgets(nome, STR_MAXLEN, stdin); nome[ strlen(nome)-1 ] = '\0' // remove '\n' lido pelo fgets if( !(arq = fopen(nome,"wb")) ) //cria (ou grava por cima), validando printf("Erro criacao"); else { // coleta dados do usuário e grava no arquivo // continua... Arquivos binários: exercício (programa 1) 42 // continuando... // coleta dados do usuário e grava no arquivo do { printf("\nNome (ate' %d letras): ", MAX_STRLEN-1); fgets(buffer.nome, MAX_STRLEN, stdin); printf("\nIdade: "); scanf("%d",&buffer.idade); printf("\nAltura: "); scanf("%f",&buffer.altura); if (fwrite(&buffer, sizeof(atleta_t), 1, arq) != 1) printf("Erro de escrita\n"); printf("\n1-InserirNovo, 2-Encerrar\n"); scanf("%i",&op); } while(op != 2); fclose(arq); //fecha } // else return 0; // Fim do programa 1 } Arquivos binários: exercício (programa 1) 43 // continuando... // coleta dados do usuário e grava no arquivo do { printf("\nNome (ate' %d letras): ", MAX_STRLEN-1); fgets(buffer.nome, MAX_STRLEN, stdin); printf("\nIdade: "); scanf("%d",&buffer.idade); printf("\nAltura: "); scanf("%f",&buffer.altura); if (fwrite(&buffer, sizeof(atleta_t), 1, arq) != 1) printf("Erro de escrita\n"); printf("\n1-InserirNovo, 2-Encerrar\n"); scanf("%i",&op); } while(op != 2); fclose(arq); //fecha } // else return 0; // Fim do programa 1 } Arquivos binários: exercício (programa 1) 44 // Programa 2 int main() { atleta_t buffer; FILE *arq; //declaração de ponteiro para arquivo char nome[STR_MAXLEN]; printf("Nome do arquivo (maximo %d caracteres): ", STR_MAXLEN-1); fgets(nome, STR_MAXLEN, stdin); nome[ strlen(nome)-1 ] = '\0' // remove '\n' lido pelo fgets if( !(arq = fopen(nome,"rb")) ) // abre para leitura, posiciona no início printf("Erro na abertura\n"); else { // listagem sequencial // continua... Arquivos binários: exercício (programa 2) 45 Arquivos binários: exercício (programa 2) // continuando... // listagem sequencial printf("-----Comeco da listagem-----\n"); while(!feof(arq)) { // enquanto não chegou no final // testa leitura, para não considerar a tentativa no final if(fread(&buffer,sizeof(atleta_t), 1,arq) == 1) { printf("Nome: %s\n", buffer.nome); printf("Idade: %d\n", buffer.idade); printf("Altura: %.2f\n\n", buffer.altura); } } printf("-----Fim da listagem-----\n"); fclose(arq); } // else return 0; // Fim do programa 2 } 46 Arquivos binários: exercício (programa 2) // continuando... // listagem sequencial printf("-----Comeco da listagem-----\n"); while(!feof(arq)) { // enquanto não chegou no final // testa leitura, para não considerar a tentativa no final if(fread(&buffer,sizeof(atleta_t), 1,arq) == 1) { printf("Nome: %s\n", buffer.nome); printf("Idade: %d\n", buffer.idade); printf("Altura: %.2f\n\n", buffer.altura); } } printf("-----Fim da listagem-----\n"); fclose(arq); } // else return 0; // Fim do programa 2 } 47 // Programa 3 int main() { atleta_t buffer; char nome[MAX_STRLEN]; FILE *arq; //declaração de ponteiro para arquivo int encontrado, op; printf("Nome do arquivo (maximo %d caracteres): ", STR_MAXLEN-1); fgets(nome, STR_MAXLEN, stdin); nome[ strlen(nome)-1 ] = '\0' // remove '\n' lido if(!(arq = fopen(nome,"rb"))) //leitura, validando printf("Erro abertura"); else { // busca // continua... Arquivos binários: exercício (programa 3) 48 // continuando... busca do { rewind(arq);// reposiciona registro corrente no início do arquivo. encontrado = 0; //indica não encontrado (ainda) printf("Nome do atleta procurado: "); fgets(procurado, MAX_STRLEN, stdin); while(!feof(arq) && !encontrado) //para qdo. acha ou no fim do arquivo if(fread(&buffer,sizeof(atleta_t),1,arq) == 1) if( strcmp(buffer.nome, procurado) == 0) { printf("\nAltura de %s: %.2fm",procurado,buffer.altura); encontrado = 1; // indica que encontrou } } if (!encontrado) printf("\nAtleta nao foi localizado."); printf("\n1-BuscarOutro, 2-Encerrar\n"); scanf("%i",&op); } while(op != 2); fclose(arq); } // else return 0; // Fim do programa 3 } Arquivos binários: exercício (programa 3) 49 // continuando... busca do { rewind(arq); // reposiciona registro corrente no início do arquivo. encontrado = 0; //indica não encontrado (ainda) printf("Nome do atleta procurado: "); fgets(procurado, MAX_STRLEN, stdin); while(!feof(arq) && !encontrado) //para qdo. acha ou no fim do arquivo if(fread(&buffer,sizeof(atleta_t),1,arq) == 1) if( strcmp(buffer.nome, procurado) == 0) { printf("\nAltura de %s: %.2fm",procurado,buffer.altura); encontrado = 1; // indica que encontrou } } if (!encontrado) printf("\nAtleta nao foi localizado."); printf("\n1-BuscarOutro, 2-Encerrar\n"); scanf("%i",&op); } while(op != 2); fclose(arq); } // else return 0; // Fim do programa 3 } Arquivos binários: exercício (programa 3) 50 // Programa 4 int main() { atleta_t buffer; FILE *arq; char nome[MAX_STRLEN]; int op; printf("Nome do arquivo (maximo %d caracteres): ", STR_MAXLEN-1); fgets(nome, STR_MAXLEN, stdin); nome[ strlen(nome)-1 ] = '\0' // remove '\n' lido if(!(arq = fopen(nome,"ab"))) // abre em "modo append" (acrescentar dados) printf("Erro na abertura para acrescentar"); else { // adiciona dados // continua... Arquivos binários: exercício (programa 4) 51 // continuando... // adiciona dados do { // gravados a partir do final do arquivo: printf("\nNome (ate' %d letras): ", MAX_STRLEN-1); fgets(buffer.nome, MAX_STRLEN, stdin); printf("\nIdade: "); scanf("%d",&buffer.idade); printf("\nAltura: "); scanf("%f",&buffer.altura); if (fwrite(&buffer,sizeof(TIPO_ATLETA),1,arq) != 1) printf("Erro na escrita\n"); printf("\n1-Inserir novo, 2-Encerrar\n"); scanf("%d", &op); } while(op != 2); fclose(arq); } // else return 0; // Fim do programa 4 } Arquivos binários: exercício (programa 4) 52 Outras funções de manipulação: ferror() 53 Outras funções de manipulação: rename(), remove() 54 Para pensar em casa... Escreva um programa que lê os dados de estudantes do ensino médio que prestaram ENEM. O seu programa deve armazenar numa struct os dados: nome do aluno (max 60 caracteres), a idade do aluno e a média final que o aluno obteve (inteiro entre 0 e 100, não precisa fazer validação). Leia os dados e armazene num arquivo binário cujo nome será lido do usuário. O programa deve parar de ler dados quando o usuário digitar a string “Sair” para o nome do aluno. Após a leitura e armazenamento dos dados no arq uivo, o programa deve solicitar ao usuário uma média qualquer e o programa deve listar o nome e média de todos os alunos que tiveram média maior ou igual à média informada. Esta informação deve ser obtida a partir da leitura do arquivo salvo. Abaixo exemplo de execução: 55
Compartilhar