6.1 Passagem de vetores para função
Exemplo 6.1.1. Escreva um programa com uma função que recebe um
vetor e devolve outro vetor contento mínimo, máximo e norma.
#include <stdio.h>
#include <math.h>
#define N 4
void teste(double x[N], double saida[3])
{
double max=x[0], norma=0, min=x[0];
int i;
for (i=0;i<N;i++)
{
norma+=x[i]*x[i];
if (max<x[i]) max=x[i];
if (min>x[i]) min=x[i];
}
saida[0]=min;
saida[1]=max;
saida[2]=sqrt(norma);
return;
}
main (void)
{
double a[N]={1,-2,3,4},saida[3];
teste(a,saida);
printf("mínimo=%f, máximo=%f, norma=%f\n",saida[0],saida[1],saida[2]);
}
Quando passamos um vetor de N posições para dentro de uma função, não
estamos levando N valores, mas um único valor que é o endereço de memória
dos vetores. Veja como chamamos a linha teste(a,saida);. Aqui a e saida
são endereços de memória dos vetores. Naturalmente, a protótipo
void teste(double x[N], double saida[3]) também funciona da forma
void teste(double *x, double *saida), pois, de fato, estamos passando um
ponteiro.
#include <stdio.h>
#include <math.h>
#define N 4
void teste(double *x, double *saida)
{
double max=*x, norma=0, min=*x;
int i;
for (i=0;i<N;i++)
{
norma+=*(x+i)**(x+i);
if (max<*(x+i)) max=*(x+i);
if (min>*(x+i)) min=*(x+i);
}
*saida=min;
saida++;
*saida=max;
saida++;
*saida=sqrt(norma);
return;
}
main (void)
{
double a[N]={1,-2,3,4},saida[3];
teste(a,saida);
printf("mínimo=%f, máximo=%f, norma=%f\n",saida[0],saida[1],saida[2]);
}
Uma versão mista do código também funciona.
Uma grande vantagem dos ponteiros é evitar a copia um vetor inteiro de uma
posição da memória para outra, mas apenas trocar um ponteiro que aponta
para o tal vetor. Isso reduz significantemente o custo computacional de um
processo iterativo.
Exemplo 6.1.2. Vamos refazer o exemplo 4.3.1, que resolve um problema
de contorno, melhorando a performance do processo iterativo com uso de
ponteiros
#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;
double *pu_antigo=u_antigo,*pu_atual=u_atual,*pswap;
//chute inicial
for (i=0;i<N;i++)u_antigo[i]=0;
//iteração
while (controle)
{
Iteracao(pu_antigo,pu_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;
pswap=pu_atual;
pu_atual=pu_antigo;
pu_antigo=pswap;
}
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-10,solucao[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;
//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]-solucao_analitica(x[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,solucao_analitica(x[i]));
}