8.5 Acesso direto e acesso sequencial
Até o momento nós abrimos os arquivos e lemos sequencialmente a partir do
início, isto é, fizemos acesso sequencial. Agora, pretendemos ler uma
posição do arquivo sem lê-lo desde o início, isto é, pretendemos acessar
diretamente um elemento. Os comandos úteis para se posicionarmos
ao longo do arquivo são: ftell, que entra um ponteiro para arquivo
e retorna a posição e rewind, que entra um arquivo e o posiciona o
início.
Exemplo 8.5.1. Reescreva um código que lê o arquivo gerado no exemplo
8.4.4, depois lê o primeiro número novamente.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double v[20],*p=v,first;
FILE *arq;
int i,ch;
long int total;
arq=fopen("saida.dat","rb");
if (arq==NULL)
printf("Não conseguiu abrir o arquivo\n");
else
{
printf("Arquivo aberto com sucesso\n");
printf("%ld\n",total=ftell(arq));
while ((ch=fread(p,sizeof(double),1,arq))!=0)
{
p++;
}
printf("%ld\n",total=ftell(arq));
rewind(arq);
printf("%ld\n",ftell(arq));
fread(&first,sizeof(double),1,arq);
printf("%ld\n",ftell(arq));
fclose(arq);
printf("Arquivo fechado com sucesso\n");
}
printf("%ld\n",total/=8);
for (i=0;i<total;i++) printf("%f\n",v[i]);
printf("first=%f\n",first);
}
A função usada para posicionamento dentro do arquivo é a
int fseek(FILE *arq,long int salto, int origem)
onde
- FILE é um ponteiro para arquivo.
- saltoé o número de bytes que desejamos andar (positivo para frente
e negativo para trás).
- origem é o local de onde queremos saltar, podemos assumir os
seguintes valores:
SEEK_SET salto realizado a partir da origem do arquivo.
SEEK_CUR salto realizado a partir da posição atual.
SEEK_END salto realizado a partir da fim do arquivo.
Exemplo 8.5.2. Reescreva um código que lê o arquivo gerado no exemplo
8.4.4, depois lê somente os três últimos.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double v[20],*p=v,last[3];
FILE *arq;
int i,ch;
long int total;
arq=fopen("saida.dat","rb");
if (arq==NULL)
printf("Não conseguiu abrir o arquivo\n");
else
{
printf("Arquivo aberto com sucesso\n");
printf("%ld\n",total=ftell(arq));
while ((ch=fread(p,sizeof(double),1,arq))!=0)
{
p++;
}
printf("%ld\n",total=ftell(arq));
fseek(arq,-24,SEEK_END);
printf("onde estou? %ld\n",ftell(arq));
fread(last,sizeof(double),3,arq);
fclose(arq);
printf("Arquivo fechado com sucesso\n");
}
printf("%ld\n",total/=8);
for (i=0;i<total;i++) printf("%f\n",v[i]);
printf("\n");
for (i=0;i<3;i++) printf("%f\n",last[i]);
}
Exemplo 8.5.3. Vamos resolver o exemplo 4.3.1 novamente imprimindo a
solução em arquivo. Vamos usar o mesmo código, ampliando apenas as
linhas que salvam em arquivo binário.
#include <stdio.h>
#include <math.h>
#define N 101 /* dimensão do sistema*/
double norma_2(double x[N])
{
int i;
double norma2=x[0]*x[0]/(2*(N-1));
for (i=1;i<N-1;i++)
{
norma2+=x[i]*x[i]/(N-1);
}
norma2+=x[N-1]*x[N-1]/(2*(N-1));
return sqrt(norma2);
}
void Iteracao(double u_antigo[N],double u_atual[N],double matriz[N][N], double vetor[N])
{
double aux;
int i,j;
for (i=0;i<N;i++)
{
aux=0;
for (j=0;j<i;j++)
aux+=matriz[i][j]*u_antigo[j];
for (j=i+1;j<N;j++)
aux+=matriz[i][j]*u_antigo[j];
u_atual[i]=(vetor[i]-aux)/matriz[i][i];
}
}
void Jacobi(double tolerancia,double u_atual[N],double vetor[N],double matriz[N][N],double malha[N])
{
double u_antigo[N],dif[N];
int i,controle=3;
//chute inicial
for (i=0;i<N;i++)u_antigo[i]=0;
//iteração
while (controle)
{
Iteracao(u_antigo,u_atual,matriz,vetor);
for (i=0;i<N;i++) dif[i]=u_atual[i]-u_antigo[i];
if (norma_2(dif)<tolerancia) controle--;
else controle=3;
for (i=0;i<N;i++) u_antigo[i]=u_atual[i];
}
return;
}
double solucao_analitica(double x)
{
return -25.*(x-1.)*(x-1.)*(x-1.)*(x-1.)/3-25.*x/3+25./3.;
}
main (void)
{
int i,j;
double tolerancia=1e-5,solucao[N],sol_anal[N];
double matriz[N][N];
double vetor[N],x[N];
//malha
double h=1./(N-1);
for (i=0;i<N;i++)
{
x[i]=i*h;
sol_anal[i]=solucao_analitica(x[i]);
}
//matriz e vetor
for (i=0;i<N;i++) for (j=0;j<N;j++) matriz[i][j]=0;
matriz[0][0]=1;
vetor[0]=0;
for (i=1;i<N-1;i++)
{
matriz[i][i]=-2;
matriz[i][i+1]=1;
matriz[i][i-1]=1;
vetor[i]=-100*h*h*(x[i]-1)*(x[i]-1);
}
matriz[N-1][N-1]=1;
vetor[N-1]=0;
Jacobi(tolerancia,solucao,vetor,matriz,x);
//erro médio
double erro=0;
for (i=0;i<N;i++) erro+=fabs(solucao[i]-sol_anal[i]);
erro/=N;
printf("erro médio = %f\n",erro);
for (i=0;i<N;i++) printf("u_%d=%f, u(x[%d]) = %f\n",i,solucao[i],i, sol_anal[i]);
FILE *arq;
arq=fopen("saida.dat","w+b");
if (arq==NULL)
printf("Erro ao abrir arquivo\n");
else
{
printf("Arquivo aberto\n");
fwrite(solucao,sizeof(double),N,arq);
fwrite(sol_anal,sizeof(double),N,arq);
printf("Gravou\n");
fclose(arq);
}
}
Observe um código em scilab para ler e fazer o gráfico das duas soluções:
N=101;
x=linspace(0,1,N);
arq=mopen(’/home/pasta/subpasta/subsubpasta/saida.dat’,’rb’)
Snum=mget(N,’d’,arq)
Sanal=mget(N,’d’,arq)
mclose(arq)
plot(x,Snum)
plot(x,Sanal,’red’)