Problema ao passar arquivo como argumento de função.

Problema ao passar arquivo como argumento de função.

por Caio Braz -
Número de respostas: 6
Bom, estou com um pequeno problema no meu EP.

As variáveis que "guardam" arquivos (declaradas como FILE *arquivo) estao dando problema toda vez que preciso passa-las como argumento de função.

Exemplo:

void funcao(FILE *arquivo, char string[])
{
    arquivo = fopen (string, "w");
}

int main ()
{
    char c;
    char string[100];
    FILE *arquivo;
    scanf ("%s", string);  
    funcao (arquivo, string);
    fprintf (arquivo, "%c", c);
    return 0;
}

Nesse exemplo, funciona tudo normal, a função funciona, tudo que está dentro dela acontece normalmente, mas ai quando o programa volta para ler o que acontece depois da função (no caso o fprintf) ele não funciona, ele cria o arquivo (fopen dentro da função) mas na hora do fprintf ele não "printa" nada no arquivo criado (ou seja o arquivo criado fica em branco). É como se o arquivo tivesse sumido aundo voltou da função.

O único jeito que eu encontrei de resolver isso foi deixar tudo que estaria dentro de uma função que recebe arquivos, dentro do main, mas isso me deixa com o problema de que nas funções obrigatórias do EP eu precisaria passar arquivo como argumento.

Como posso resolver esse problema?
Em resposta à Caio Braz

Re: Problema ao passar arquivo como argumento de função.

por Rodrigo Cordeiro Godoy -

É... eu tive o mesmo problema.

Resolvi ele exatamente como vc disse... eu fecho o arquivo sempre na mesma função que o abriu (seja ela main ou não (não no meu caso hehehe)) passando o arquivo para as funções que se interessam com ele como um argumento.

Em resposta à Caio Braz

Re: Problema ao passar arquivo como argumento de função.

por Henrique Stagni -

Talvez o problema seja que arquivo é um ponteiro que ainda não está apontando para lugar nenhum quando voçê chama a função. Estou conseguindo mandar variáveis do tipo FILE entre funções tendo o cuidado de sempre iniciar elas com um fopen antes de mandá-la como argumento.

Acho que não é bem isso que voçê queria, mas de qualquer forma colokei um exemplo que usa uma variavel FILE como argumento

                          EXEMPLO:


#include <stdio.h>
void EscreveOiNoArquivo(FILE *arquivo)
{
    fprintf(arquivo, "OI!");
}

int main ()
{
    char string[100];
    FILE *arquivo;
    scanf ("%s", string);
    arquivo=fopen(string, "w"); /*agora que a variavel aponta para o arquivo...*/
    EscreveOiNoArquivo(arquivo);/*...posso passá-la como argumento*/

    return 0;
}


 
Em resposta à Henrique Stagni

Re: Problema ao passar arquivo como argumento de função.

por Caio Braz -
Então, isso sempre funcionou pra mim, o problema é quando eu tenho um comando que mexe no arquivo depois que ele foi pra função, no seu exemplo:

#include <stdio.h>
void EscreveOiNoArquivo(FILE *arquivo)
{
    fprintf(arquivo, "OI!");
}

int main ()
{
    char string[100];
    FILE *arquivo;
    scanf ("%s", string);
    arquivo=fopen(string, "w"); /*agora que a variavel aponta para o arquivo...*/
    EscreveOiNoArquivo(arquivo);/*...posso passá-la como argumento*/
    fprintf(arquivo, "\nTESTE") /* o meu da problema nesse tipo de comando, que vem depois que o arquivo "volta" da função, ele simplesmente não executa o comando */

    return 0;

}

O problema é quando "volta" pro main, ai ele parece que não reconhece mais o arquivo.
Em resposta à Caio Braz

Re: Problema ao passar arquivo como argumento de função.

por Rodrigo Luiz Marques Flores -
Sugestão:

Criem uma função assim:

 FILE* abrearquivo (char* nome )
{
    FILE* abriu;
    abriu = fopen(nome,"w");
    return abriu;
}

Fica mais fácil (e não precisa usar ponteiro pra ponteiro (que seria necessário para fazer do jeito q vcs querem))
PS: Aqui eu não tratei, mas tratem os possíveis erros de abertura.
Em resposta à Caio Braz

Re: Problema ao passar arquivo como argumento de função.

por Henrique Stagni -

Pelo menos aqui, a alteração que vc fez deu certo e o arquivo ficou com o conteudo:


OI!
TESTE


mas o jeito do rodrigo deve funcionar melhor,,,:D

 

Em resposta à Caio Braz

Re: Problema ao passar arquivo como argumento de função.

por Francisco Reverbel -
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).