Não há nenhum problema em passar um parâmetro FILE *arquivo para uma função, mas se a função alterar o valor desse parâmetro, executando uma atribuição como
arquivo = fopen(string, "w");
a alteração só será válida dentro da função! Esse é o problema com o código que o Caio postou na primeira mensagem desta thread.
Analisando em detalhes... A linha
FILE *arquivo;
declara uma variável tipo ponteiro que não está inicializada. Essa variável serve para apontar para um FILE (seja lá o que isso for), mas (por enquanto) ela não aponta para nada, ou seja, ela contém "lixo", em vez de conter o endereço de algum FILE. Uma variável como essa é geralmente inicializada por uma atribuição
arquivo = fopen(string, "w");
É essa atribuição que coloca na variável arquivo o endereço (devolvido pela chamada a fopen) de um FILE!
Agora vejamos este trecho do programa que o Caio postou:
FILE *arquivo;
scanf("%s", string);
funcao(arquivo, string);
fprintf(arquivo, "%c", c);
Lembrem-se que na passagem de parâmetros o que ocorre é uma cópia dos valores passados como parâmetros. Ou seja, a funcao do Caio recebe uma cópia do lixo contido na variável arquivo. Embora ela atualize essa cópia com o endereço devolvido pela chamada fopen, a atualização só vale dentro da funcao! O endereço é perdido quando a funcao volta para quem a chamou. Quando é executado o fprintf(arquivo, "%c", c), a variável arquivo contém exatamente o mesmo lixo que ela continha antes da chamada à funcao!
A maneira mais fácil de resolver esse problema é a que o Rodrigo indicou. Outra forma (mais complicada, que é bom conhecer mas não vale a pena usar neste caso) é usar um ponteiro para um ponteiro, ou seja passar à funcao o endereço de um ponteiro para que ela possa inicializar o ponteiro:
void funcao(FILE **arq, char string[])
{
*arq = fopen(string, "w");
}
int main()
{
char c;
char string[100];
FILE *arquivo;
scanf("%s", string);
funcao(&arquivo, string);
fprintf(arquivo, "%c", c);
return 0;
}
Agora a declaração do primeiro parâmetro da função (FILE **arq) diz que ele é um ponteiro (o * mais à direita) para um FILE *. Em outras palavras, arq é o endereço de um FILE *, e *arq é um FILE *. A função agora usa esse ponteiro para inicializar o FILE * apontado por ele com o endereço devolvido por fopen. Notem que, na chamada a função, é passado o endereço (&) da variável arquivo, cujo tipo é FILE *.
Como ponteiros para ponteiros são uma coisa mais complicada e difícil de entender, eles só devem ser usados quando realmente houver necessidade. Quando a solução do Rodrigo (devolver o FILE * como valor da função) for aplicável, ela deve ser preferida. Usem ponteiros para ponteiros apenas quando essa solução não for aplicável: caso vocês precisem de uma função que devolva mais de um ponteiro (um FILE *f1 e um FILE *f1, por exemplo -- só um deles pode ser devolvido como valor da função, o outro terá que ser devolvido através de um argumento como FILE **endereco_de_FILE_ptr).
Re: Problema ao passar arquivo como argumento de função.
por Francisco Reverbel -
Número de respostas: 0