View Full Version : Criar ficheiro com struct em C
Catrabinas 31-01-2008, 16:32 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:
#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?
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);
}
petersaints 31-01-2008, 20:15 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);
}
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?
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?
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.
petersaints 31-01-2008, 20:41 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.
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?
MadOnion 31-01-2008, 20:46 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?
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:
#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.
petersaints 31-01-2008, 21:09 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
MadOnion 31-01-2008, 21:27 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.
AliFromCairo 31-01-2008, 22:09 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
Sim, é isso.
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.
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).
MadOnion 31-01-2008, 22:44 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).
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.
Se se usar um vector(ou array) para guardar a informação a leitura e escrita fica mais simplificada, ficando algo como:
//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.
Catrabinas 12-02-2008, 10:16 Obrigado a todos pela ajuda! Já consegui:001:
Faulk_08 07-07-2008, 16:01 Obrigado a todos pela ajuda! Já consegui:001:
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
Mr. Brightside 07-07-2008, 20:32 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
Não será melhor dizeres quais as dúvidas que tens e nós tentamos ajudar?
Faulk_08 07-07-2008, 21:57 Não será melhor dizeres quais as dúvidas que tens e nós tentamos ajudar?
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?????
Boas é semelhante ao que já foi explicado aqui nesta thread ... dá uma vista de olhos...
Faulk_08 08-07-2008, 20:59 Boas é semelhante ao que já foi explicado aqui nesta thread ... dá uma vista de olhos...
Pois eu ja dei uma vista de olhos mas nao me consegui resolver o problema???
Ajudem-me....
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);
}
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.
Faulk_08 09-07-2008, 11:28 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.
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
printf("Introduza o nome: ");
gets(&ptr->Nome);????????
Baderous 09-07-2008, 11:49 Não declaraste o ptr em lado nenhum.
Faulk_08 09-07-2008, 21:29 Não declaraste o ptr em lado nenhum.
ya e como vou declarar isso???
Baderous 09-07-2008, 21:37 Dentro da função, tal e qual como quando declaras outra variável.
Faulk_08 10-07-2008, 11:12 Dentro da função, tal e qual como quando declaras outra variável.
Mas vou declara-la de que tipo????
Baderous 10-07-2008, 11:14 Sendo prt um apontador tens que declarar que ele aponta para o tipo da estrutura.
Mas vou declara-la de que tipo????
do tipo da tua estrutura pessoal:
struct pessoal ptr;
Baderous 10-07-2008, 11:18 do tipo da tua estrutura pessoal:
struct pessoal ptr;
Melhor ainda:
Agente *ptr;
E assim tiras aqueles & antes dos ptrs, que só está lá a acumular lixo.
Faulk_08 11-07-2008, 01:37 Melhor ainda:
Agente *ptr;E assim tiras aqueles & antes dos ptrs, que só está lá a acumular lixo.
Brigado.Resolvi um problema so que agora da-me erro no Nasc
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");
Agente *ptr;
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);
}
}
O erro é aqui no Nasc
printf("Introduza o dia nascimento: "); scanf("%d", ptr->Nasc.Dia);
Brigado.Resolvi um problema so que agora da-me erro no Nasc
Data Nascimento;
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);
O erro é aqui no Nasc
tens declarado Nascimento e não Nasc ;)
Faulk_08 12-07-2008, 16:11 tens declarado Nascimento e não Nasc ;)
Brigadao.Agora ja nao me da erro nenhum mas quando vou a correr sim da-me erro..... :confused:
http://img34.picoodle.com/img/img34/4/7/12/t_blaam_fd5668b.jpg (http://www.picoodle.com/view.php?img=/4/7/12/f_blaam_fd5668b.jpg&srv=img34)
|
|