1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Criar ficheiro com struct em C

Discussão em 'Programação' iniciada por Catrabinas, 31 de Janeiro de 2008. (Respostas: 28; Visualizações: 7878)

  1. Catrabinas

    Catrabinas Power Member

    Boas pessoal..

    a minha duvída é a seguinte: eu tenho um programa em C com struct e tenho de o abrir e guardar em ficheiro.. o programa é este:

    Código:
    #include <stdio.h>
    #include <conio.h>
    typedef struct {int Dia,Mes,Ano;} DATA;
    typedef struct pessoa
    {
     char Nome[100];
     int Idade;
     int Salario;
     DATA Nasc;
    } PESSOA;
    
    void ler_pessoa(PESSOA *ptr)
    {
     printf("Introduza o nome: "); gets(ptr->Nome);
     printf("Introduza a idade: "); scanf("%d", &ptr->Idade);
     printf("Introduza o salario: "); scanf("%d", &ptr->Salario);
     printf("Introduza o dia nascimento: "); scanf("%d", &ptr->Nasc.Dia);
     printf("Introduza o mes nascimento: "); scanf("%d", &ptr->Nasc.Mes);
     printf("Introduza o ano nascimento: "); scanf("%d", &ptr->Nasc.Ano);
    }
    void Mostrar(struct pessoa x)
    {
     printf("Nome        : %s \n",x.Nome);
     printf("Idade       : %d \n",x.Idade);
     printf("Salario     : %d \n",x.Salario);
     printf("Data Nasc.  : %d/%d/%d \n",x.Nasc.Dia,x.Nasc.Mes,x.Nasc.Ano);
    }
    void main(void)
    {
       struct pessoa p;
       ler_pessoa(&p);
       Mostrar(p);
       abrir_fich(&p);
       getch();
    }
    alguem sabe como ficaria o programa?
     
    Última edição pelo moderador: 7 de Julho de 2008
  2. AragTey

    AragTey Power Member

    Código:
    
    FILE *f = fopen(nome_do_fich, "wb"); // abrir escrita do ficheiro em binário
    if (f != NULL)
    {
       fwrite(&p, sizeof(pessoa), 1, f);  // escrever uma estrutura do tipo pessoa
       fclose(f);
    }
    
     
  3. petersaints

    petersaints Power Member


    Yah eu já fiz isso num projecto de C uma vez (perdi a source :( entretanto). Mas acho que usei fprintf e fscanf para escrever e ler mas este método parece ser mais straightforward e para ler basta usar fread? Já agora porque é que tem que ser em binário? É coisa que nunca percebi... qual a diferença de gravar em binário ou em texto?
     
  4. AragTey

    AragTey Power Member

    Não tem de ser em binário, mas no caso de estruturas penso que é mais facil, porque apenas gravas o que tens em memária, sem te preocupares com o tipo de variável. Alem disso em binário ocupa menos espaço. Em binário não consegues perceber o que está no ficheiro e em texto consegues.

    Sim basta usar fread para ler, mas tens de saber a quantidade que vais ler, isto é, se por exemplo se graver um array de struct pessoa tens de gravar primeiro um numero com a quantidade, para depois leres isso tudo.
     
  5. petersaints

    petersaints Power Member

    Como assim? Esse número seria gravado como?

    P.S.:
    fwrite(&p, sizeof(pessoa), 1, f);Os argumentos do fwrite querem dizer o que?
    &p é o nome da variável pessoa p?
    o sizeof é para saber o tamanho suponho
    o 1 é o que? só uma entrada?
    e o f é o pointer do ficheiro certo?
     
  6. MadOnion

    MadOnion Folding Member

    Em binário, o sistema operativo entende que "cada linha do ficheiro" contém uma struct. O que está dentro da struct não interessa, interessa é que contem uma struct.
    Fica complicado se guardares num ficheiro de texto, todos os campos de uma struct, é completamente ilegivél.
    Grava-se para um ficheiro binário uma struct, depois retira-se desse ficheiro binário a mesma struct, "desdobra-se" dentro do programa e dás o destino que bem entenderes.
    Para imprimir o seu conteúdo, podes usar o fprintf, em stdout ou para outro ficheiro de formato texto(e portanto, legivel).

    Edit:
    Código:
     #include <stdio.h>
    
         size_t
         fread(void *restrict ptr, size_t size, size_t nitems,
             FILE *restrict stream);
    
         size_t
         fwrite(const void *restrict ptr, size_t size, size_t nitems,
             FILE *restrict stream);
    
    Exacto os parametros querem dizer isso.
    O apontador para a struct onde vais guardar a struct lida do ficheiro.
    O tamanho da struct.
    O número de itens a ser lido
    E o filepointer.
     
    Última edição: 31 de Janeiro de 2008
  7. petersaints

    petersaints Power Member

    Yeah I got it ;) Só uma cena o número de itens a ser lido vai depender do tamanho da base de dados (por assim dizer) se eu definir um vector, por exemplo struct pessoa p[100], da estrutura como sei quanto estão guardados? (NO EXEMPLO APRESENTADO ELE APENAS TINHA 1 PESSOA)

    Este thread nem é meu mas fez-me relembrar e despertar a curiosidade :P
     
  8. MadOnion

    MadOnion Folding Member

    Código:
    int contador = 0;
    
    /*O fread quando não tiver mais nada para ler, devolve -1, se não estou em erro*/
    while (contador < 100 && (fread(&p, sizeof(pessoa), 1, f) != -1)) {
    
    (...)
    }
    
    A leitura é feita um por um, ele pára quando o contador chegar ao fim, ou quando o ficheiro estiver sem dados.
     
  9. AliFromCairo

    AliFromCairo Power Member

    Sim, é isso.

    Ler um a um não é particularmente eficiente. É para evitar isso que serve o terceiro argumento da função. Para além disso, no código que colocaste, vais ficar apenas com o último elemento, na primeira posição, que não é o que se pretende :007:. Para funcionar correctamente, o primeiro argumento deveria ser &p + contador * sizeof(pessoa).
     
  10. MadOnion

    MadOnion Folding Member

    Na minha abordagem, o &p é uma struct auxiliar que contém cada struct lida actualmente.
    Posteriormente essa struct seria guardada/copiada para um vector de structs, no indice i, e continuava com a leitura até a guarda do while ser falsa.
    Eu não sei até que ponto o size_t nitems é eficiente, ou seja, se eu disser que quero guardar 100, e o ficheiro só conter 20 structs, foi uma situação que nunca testei, mas também é facilmente explorável.
     
  11. AragTey

    AragTey Power Member

    Se se usar um vector(ou array) para guardar a informação a leitura e escrita fica mais simplificada, ficando algo como:

    Código:
    //write
    int size = vect_pessoas.size();
    putw(size, f);
    fwrite(pessoas.begin(), sizeof(pessoa), size, f);
    fclose();
    
    // read algo semelhante a:
    size = getw(f); 
    vect_pessoas.resize(size);
    if (size > 0)
    if (fread(vect_pessoas.begin(), sizeof(pessoa), size, f) != size)
    fclose(f);
    
    Simplificando a escrita\leitura comeca na posicao de memoria onde está o inicio do vector e reserva na memoria, size*sizeof(pessoa) para a escrita\leitura.
     
  12. Catrabinas

    Catrabinas Power Member

    Obrigado a todos pela ajuda! Já consegui:001:
     
  13. Boas,
    Eu também estou com o mesmo problema em trabalhar com estruturas com ficheiros.
    Será que me podias disponibilizar o teu programa na totalidade resolvido para poder tirar as minhas duvidas??
    Agradecia imenso
    Obrigado
     
  14. Não será melhor dizeres quais as dúvidas que tens e nós tentamos ajudar?
     
  15. Código:
    typedef struct {int Dia,Mes,Ano;}Data;
    typedef struct pessoal
        {
        char Nome[100];
        char Genero[100];
        Data Nascimento;
        int Nmc;
        int Nmf;
    }Agente;
    void criar_agente(char nometxt[]){
        FILE *file = fopen(nometxt, "ab");
        if (file != NULL)
        {    
            printf("Introduza o nome: "); 
            gets(ptr->Nome);
            printf("Introduza o genero: "); 
            gets(ptr->Genero);
            printf("Introduza o dia nascimento: "); 
            scanf("%d", &ptr->Nasc.Dia);
            printf("Introduza o mes nascimento: "); 
            scanf("%d", &ptr->Nasc.Mes);
            printf("Introduza o ano nascimento: "); 
            scanf("%d", &ptr->Nasc.Ano);
            printf("Introduza o numero de missoes concluidas com sucesso: ");
            scanf("%d", &ptr->Nmc);
            printf("Introduza o numero de missoes falhadas: "); 
            scanf("%d", &ptr->Nmf);
               
        }
    
    Como poderei agora escrever num ficheiro?????
     
  16. AragTey

    AragTey Power Member

    Boas é semelhante ao que já foi explicado aqui nesta thread ... dá uma vista de olhos...
     
  17. Pois eu ja dei uma vista de olhos mas nao me consegui resolver o problema???
    Ajudem-me....
     
    Última edição: 9 de Julho de 2008
  18. AragTey

    AragTey Power Member

    Abres o ficheiro de escrita em modo binario e depois usas o fwrite onde passsa como argumentos a estrutura que queres escrever, o tamanho, dessas estrutura a quantidade de estruturas desse tipo que vais escrever e por fim o ponteiro para o ficheiro.

    http://www.cplusplus.com/reference/clibrary/cstdio/fwrite.html

    EDIT: no teu caso em vez da estrutura pessoa tem pessoal.
     
  19. Código:
    typedef struct {int Dia,Mes,Ano;}Data;
    typedef struct pessoal
        {
        char Nome[100];
        char Genero[100];
        Data Nascimento;
        int Nmc;
        int Nmf;
    }Agente;
    void criar_agente(char nometxt[]){
        FILE *file = fopen(nometxt, "ab");
        if (file != NULL)
        {    
            printf("Introduza o nome: "); 
            gets(&ptr->Nome);
            printf("Introduza o genero: "); 
            gets(&ptr->Genero);
            printf("Introduza o dia nascimento: "); scanf("%d", &ptr->Nasc.Dia);
            printf("Introduza o mes nascimento: "); scanf("%d", &ptr->Nasc.Mes);
            printf("Introduza o ano nascimento: "); scanf("%d", &ptr->Nasc.Ano);
            printf("Introduza o numero de missoes concluidas com sucesso: ");
            scanf("%d", &ptr->Nmc);
            printf("Introduza o numero de missoes falhadas: "); 
            scanf("%d", &ptr->Nmf);
               fwrite(&ptr, sizeof(Agente), 1, file);
               fclose(file);
        }
    
    }
    
    Ja modifiquei so que mesmo assim da-me erro na linha abaixo
    Código:
    printf("Introduza o nome: "); 
    gets(&ptr->Nome);
    ????????
     
  20. Baderous

    Baderous Banido

    Não declaraste o ptr em lado nenhum.
     

Partilhar esta Página