Baixe o app para aproveitar ainda mais
Prévia do material em texto
© ELFS 184 Arquivos de Dados • Imagine a seguinte situação: • Um programa precisa ler duas matrizes 10 x 10. • O usuário terá que digitar 200 valores. • O programa vai precisar ser executado novamente. • O usuário terá que digitar os 200 valores novamente. • Como evitar isso? Armazenando os valores em um arquivo e, sempre que o programa for executado, efetuar a leitura dos valores a partir do arquivo. • Arquivos são usados para armazenar dados de forma permanente (lembrar que o armazenamento de dados na memória do computador é temporário, isto é, os dados se perdem quando o programa termina sua execução). © ELFS 185 • Aplicações empresariais como, por exemplo, cadastro de clientes, controle de estoque, gestão financeira, processam muitos dados e não seriam possíveis sem o uso de arquivos. • Arquivos são armazenados em dispositivos de memória externos e podem reter grandes volumes de dados por longos períodos de tempo. • Como são externos, os arquivos não fazem parte de programas. Os programas apenas utilizam os arquivos. • A linguagem C não impõe estrutura alguma aos arquivos. Para um programa C, um arquivo é simplesmente uma sequência de bytes. • Para utilizar um arquivo de dados, é preciso declarar um ponteiro para o tipo FILE. FILE *arq; © ELFS 186 • A variável arq representa no programa o nome interno de um arquivo (externo) de dados. • Para que o arquivo possa ser utilizado no programa é preciso informar onde o arquivo se encontra (uma vez que o arquivo é externo ao programa). • Esta operação é conhecida como abertura do arquivo e é executada pela função fopen. • A função fopen tem 2 parâmetros do tipo string. O primeiro parâmetro especifica o nome do arquivo (que deve incluir a pasta onde o arquivo se encontra). FILE *arq; arq = fopen("dados.txt","r"); arq = fopen("c:\\arquivos\\dados.txt","r"); © ELFS 187 • Se a pasta não for informada, considera-se que o arquivo esteja presente na mesma pasta que contém o programa. • Se, por alguma razão, o arquivo não puder ser aberto, a função fopen irá retornar o valor NULL. • O segundo parâmetro da função fopen especifica o que se pretende fazer. As possibilidades são: • "r": Ler os dados existentes ("read"); • "w": Escrever dados, apagando os existentes ("write"); • "a": Anexar novos dados aos já existentes ("append"). FILE *arq; arq = fopen("dados.txt","r"); if (arq == NULL) { printf("Erro ao abrir o arquivo"); return 0; } © ELFS 188 • Resumindo: Modo Significado “r” Abre um arquivo existente para leitura de dados; se o arquivo não existir, irá ocorrer um erro. “w” Abre um novo arquivo para gravação de dados; se o arquivo já existir, a gravação irá sobrescrever os dados existentes. “a” Abre um arquivo para anexação de dados; se o arquivo não existir, será criado um novo arquivo. © ELFS 189 • Imagine que o arquivo dados.txt contém os seguintes dados: • Para ler o dados do arquivo, deve-se usar a função fscanf. Exemplo: Para criar um arquivo no ambiente CETUS, use sempre a extensão .txt para o nome do arquivo. 3 5 1 3 2 6 8 3 2 0 9 1 7 2 4 3 7 2 7 3 8 8 3 0 1 9 1 5 5 2 0 6 Dimensões das matrizes Linhas das matrizes ma mb fscanf(arq,"%d %d",&nl,&nc); for (i = 0; i < nl; i++) for (j = 0; j < nc; j++) fscanf(arq,"%d",&ma[i][j]); © ELFS 190 • Observe que a leitura depende da disposição dos dados no arquivo. Por exemplo, se os dados estivessem dispostos como: a leitura seria: fscanf(arq,"%d %d",&nl,&nc); for (i = 0; i < nl; i++) { for (j = 0; j < nc; j++) fscanf(arq,"%d",&ma[i][j]); for (j = 0; j < nc; j++) fscanf(arq,"%d",&mb[i][j]); } 3 5 1 3 2 6 8 2 7 3 8 8 3 2 0 9 1 3 0 1 9 1 7 2 4 3 7 5 5 2 0 6 ma mb © ELFS 191 • Depois que os dados foram lidos, deve-se fechar o arquivo usando a função fclose: • Se o fechamento do arquivo for bem sucedido, a função fclose retorna o valor 0. Caso contrário, retorna o valor -1. • Todos os arquivos abertos que não forem fechados pela função fclose, serão fechados quando o programa terminar sua execução. • Para escrever dados em um arquivo, deve-se usar a função fprintf. Para isso, o arquivo deve ser aberto no modo "w" ou "a". Exemplo: gerar uma matriz N x N com valores aleatórios e gravar no arquivo matriz.txt. fclose(arq); © ELFS 192 int i,j,N,M[50][50]; FILE *f; N = aleatorio(1,50); for (i = 0; i < N; i++) for (j = 0; j < N; j++) M[i][j] = aleatorio(10,99); f = fopen("matriz.txt","w"); if (f == NULL) { printf("Erro ao abrir o arquivo"); return 0; } fprintf(f,"%d\n",N); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) fprintf(f,"%3d",M[i][j]); fprintf(f,"\n"); } fclose(f); © ELFS 193 • Exercício. Gerar, aleatoriamente, uma matriz D de distâncias entre N cidades e gravar a matriz gerada no arquivo dist.txt. A matriz D deve ser simétrica (D[i][j] deve ser igual a D[j][i]). Além disso, D[i][i] = 0. O valor de N deve ser fornecido pelo usuário (MAX = 50). • Como garantir que a matriz gerada seja simétrica? • Linha 0: gerar os elementos das colunas 1, 2, ..., N-1 • Linha 1: gerar os elementos das colunas 2, ..., N-1 ... • Linha i: gerar quais elementos? 0 8 5 2 0 4 7 0 3 0 Uma ideia é gerar aleatoriamente apenas os elementos que estão acima da diagonal principal. © ELFS 194 #define MAX 50 int main() { int i,j,N,D[MAX][MAX]; FILE *sai; printf("Quantas cidades? "); scanf("%d",&N); // Diagonal principal for (i = 0; i < N; i++) { D[i][i] = 0; } // Acima da diagonal for (i = 0; i < N; i++) { for (j = i+1; j < N; j++) { D[i][j] = aleatorio(10,99); D[j][i] = D[i][j]; } } © ELFS 195 // Abrir arquivo para escrita sai = fopen("dist.txt","w"); if (sai == NULL) { printf("Erro ao abrir arquivo dist.txt"); return 0; } // Escrever os dados no arquivo for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { fprintf(sai,"%3d",D[i][j]); } fprintf(sai,"\n"); } // Fechar o arquivo fclose(sai); return 0; } © ELFS 196 • As funções scanf e printf são usadas apenas para os dispositivos padrões de entrada (stdin) e de saída (stdout). • Alguns dispositivos padrões: • As funções fscanf e fprintf são generalizações das funções scanf e printf, podendo ser usadas para qualquer tipo de arquivo. Nome Dispositivo Significado stdin Teclado Dispositivo padrão de entrada stdout Vídeo Dispositivo padrão de saída stdprn Porta paralela Dispositivo padrão de impressão scanf (...) é equivalente a fscanf(stdin, ...) printf(...) fprintf(stdout, ...) © ELFS 197 • Exercício. Considere que o arquivo pessoas.txt armazena a idade (int) e o peso (float) de N pessoas. O valor de N encontra-se na primeira linha do arquivo. Fazer um programa para mostrar qual é a pessoa mais jovem e qual é a pessoa mais pesada. int main() { FILE *arq; int np,N,idade,mIdade,jovem,gordo; float peso,mPeso; arq = fopen("pessoas.txt","r"); if (arq == NULL) { printf("Erro ao abrir arquivo pessoas.txt\n"); return 0; } fscanf(arq,"%d",&N); 50 28 35.6 13 18.5 21 40.9 44 51.7 ... © ELFS 198 mIdade = 1000; mPeso = 0; for (np = 1; np <= N; np++) { fscanf(arq,"%d %f",&idade,&peso); if (idade < mIdade) { mIdade = idade; jovem = np; } if (peso > mPeso) { mPeso = peso; gordo = np; } } fclose(arq); printf("%d e' a mais jovem (idade = %d)\n",jovem,mIdade); printf("%d e' a mais pesada (peso = %.2f)\n",gordo,mPeso); return 0; } © ELFS 199 • E se o arquivo não contém, na primeira linha, o número de pessoas? • Quantas linhas devem ser lidas? 28 35.6 13 18.5 21 40.9 44 51.7 ... • Devem ser lidas tantas linhas até se chegarao final do arquivo. O final do arquivo é detectado pela função feof() (eof significa end-of-file). • Como a função feof() detecta o final de um arquivo? Quando houver uma tentativa de leitura de uma nova linha do arquivo (que não existe!). • Portanto, feof(arq) retorna: • true, se após uma tentativa de leitura, constata-se que o arquivo arq não contém mais linhas a serem lidas; • false, se uma tentativa de leitura foi bem sucedida. Importante: Ao final de cada linha do arquivo deve haver uma mudança de linha ("\n"), inclusive na última linha que contém dados. © ELFS 200 • Então, quando se sabe o número de linhas do arquivo: • Quando não se sabe o número de linhas do arquivo: • Observar que a execução da função feof() deve ser precedida pela execução da função fscanf(). for (np = 1; np <= N; np++) { fscanf(arq,"%d %f",&idade,&peso); ... } np = 0; fscanf(arq,"%d %f",&idade,&peso); while (!feof(arq)) { np++; ...(processar a linha lida) fscanf(arq,"%d %f",&idade,&peso); } © ELFS 201 • Exercício. Um banco armazena em cada linha do arquivo clientes.txt as seguintes informações: código do cliente (int) e o saldo (float) de sua conta no início do mês. O banco armazena em cada linha do arquivo lancamentos.txt as seguintes informações: código do cliente (int), código do lançamento (1 = entrada; -1 = saída), valor do lançamento (float). Escrever um programa que, dado um código de cliente, mostra o total de entradas, o total de saídas e o saldo atual da conta deste cliente. 101 2580.25 118 1540.50 123 -500.00 125 1500.00 ... clientes.txt 101 1 25.25 101 1 30.00 123 -1 15.50 123 -1 100.00 101 -1 15.80 118 1 500.00 101 -1 32.00 ... lancamentos.txt Qual é o saldo do cliente 101? 2580.25 + 25.25 + 30.00 – 15.80 – 32.00 = 2587.70 © ELFS 202 #include <stdio.h> #include <stdlib.h> int main() { FILE *cli,*lan; int nc,cliente,tipo,achei; float saldo,valor,totEnt,totSai; cli = fopen("clientes.txt","r"); if (cli == NULL) { printf("Erro ao abrir arquivo clientes.txt\n"); return 0; } lan = fopen("lancamentos.txt","r"); if (lan == NULL) { printf("Erro ao abrir arquivo lancamentos.txt\n"); return 0; } printf("Qual cliente? "); scanf("%d",&nc); © ELFS 203 // Recuperar o saldo inicial do cliente achei = 0; fscanf(cli,"%d %f",&cliente,&saldo); while (!feof(cli)) { if (cliente == nc) { achei = 1; break; } fscanf(cli,"%d %f",&cliente,&saldo); } fclose(cli); if (achei == 0) { printf("Cliente %d nao existe!\n",nc); return 0; } © ELFS 204 // Recuperar os lancamentos do cliente totEnt = 0; totSai = 0; fscanf(lan,"%d %d %f",&cliente,&tipo,&valor); while (!feof(lan)) { if (cliente == nc) { if (tipo == 1) totEnt = totEnt + valor; else totSai = totSai + valor; } fscanf(lan,"%d %d %f",&cliente,&tipo,&valor); } fclose(lan); printf("Cliente %d\n",nc); printf("Saldo inicial = %.2f\n",saldo); printf("Total de entradas = %.2f\n",totEnt); printf("Total de saidas = %.2f\n",totSai); saldo = saldo + totEnt - totSai; printf("Saldo atual = %.2f\n",saldo); return 0; } © ELFS 205 • Exercício. Escrever um programa que, dado o valor de N, gera uma matriz M (N x N) com valores aleatórios no intervalo [0, 9], chama a função void contagem(int N, int M[][10], int C[]), que determina o vetor C, e escreve no arquivo conta.txt quantas vezes cada elemento de M aparece na matriz. Observar que o valor de C[k] deve ser igual ao número de vezes em que k aparece na matriz M. Exemplo: 2 4 6 3 9 6 9 3 9 9 1 7 0 4 6 6 3 3 1 2 9 7 6 9 7 0 aparece 1 vezes 1 aparece 2 vezes 2 aparece 2 vezes 3 aparece 4 vezes 4 aparece 2 vezes 5 aparece 0 vezes 6 aparece 5 vezes 7 aparece 3 vezes 8 aparece 0 vezes 9 aparece 6 vezes Matriz gerada: Arquivo conta.txt: © ELFS 206 #include <stdio.h> #include <stdlib.h> #include <time.h> int aleatorio(int a, int b) { return (a + rand()%(b-a+1)); } void contagem(int N, int M[][10], int C[]) { int i,j,x; for (i = 0; i < 10; i++) C[i] = 0; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { x = M[i][j]; C[x]++; } } return; } © ELFS 207 int main() { int i,j,N,M[10][10],C[10]; FILE *arq; srand((unsigned)time(NULL)); printf("Tamanho: "); scanf("%d",&N); if (N > 10) { printf("Erro: Tamanho maximo = 10\n"); return 0; } printf("Matriz gerada:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { M[i][j] = aleatorio(0,9); printf("%d ",M[i][j]); } printf("\n"); } © ELFS 208 contagem(N,M,C); arq = fopen("conta.txt","w"); for (i = 0; i < 10; i++) { fprintf(arq,"%d aparece %d vezes\n",i,C[i]); } fclose(arq); printf("Arquivo conta.txt gerado!\n"); return 0; } • Exercício. Modificar o programa de modo que, no arquivo conta.txt sejam mostrados apenas os elementos que aparecem 1 ou mais vezes na matriz M. • Exercício: Modificar o programa para incluir também no arquivo conta.txt a mensagem de qual foi o elemento que apareceu mais vezes na matriz M. © ELFS 209 • Exercício. Uma empresa armazena no arquivo dados.txt as seguintes informações sobre os funcionários da empresa: matrícula, salário-base (sb), número de faltas (nf), número de horas-extras (he). O salário a ser pago para cada funcionário é definido por: salário = sb × ( (30 – nf) / 30 + 1,5 × he / 240 ) Fazer um programa que lê as informações do arquivo dados.txt e escreve no arquivo folha.txt a matrícula e o valor do salário para cada um dos funcionários da empresa. O programa deve mostrar o valor total da folha de pagamentos da empresa e também escrever no arquivo folha.txt esse valor total. © ELFS 210 #include <stdio.h> #include <stdlib.h> int main() { int i,mat,nf,he; float sb,sal,total; FILE *arq,*sai; arq = fopen("dados.txt","r"); if (arq == NULL) { printf("Erro ao abrir dados.txt\n"); return 0; } sai = fopen("folha.txt","w"); if (sai == NULL) { printf("Erro ao abrir folha.txt\n"); return 0; } © ELFS 211 total = 0; fscanf(arq,"%d %f %d %d",&mat,&sb,&nf,&he); while (!feof(arq)) { sal = sb*((30.0-nf)/30 + 1.5*he/240); fprintf(sai,"%d %.2f\n",mat,sal); total = total + sal; fscanf(arq,"%d %f %d %d",&mat,&sb,&nf,&he); } printf("Total da folha de pagamento = %.2f\n",total); fprintf(sai,"%.2f\n",total); fclose(arq); fclose(sai); return 0; }
Compartilhar