Gravar dados de uma struct em arquivo binário na linguagem C.

1. Gravar dados de uma struct em arquivo binário na linguagem C.

Falcão
falke

(usa Ubuntu)

Enviado em 25/05/2015 - 22:01h

Boa noite, pessoal, desculpe o incomodo mas estou realmente perdido em um trabalho. Preciso gravar uma struct em arquivos binários e depois fazer o programa ler os dados guardados, porém não estou conseguindo, alguém poderia me informar uma ideia de sintaxe? estou fazendo assim para gravar no momento:
fwrite(&ficha, sizeof(Cliente), 1, ptarq);

Sendo ficha a variável criada e Cliente a estrutura de dados.

Muito grato desde já.


  


2. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 26/05/2015 - 01:09h

Parece que você está gravando corretamente.

Se não estiver funcionando, pode ser consequência do modo como você abriu o arquivo. Pode mostrar como foi?

Aliás, como você sabe que não está funcionando? Tem como você mostrar o fread() correspondente?

Pode ser útil também conhecer maiores detalhes da sua estrutura Cliente. Se algum dos campos dentro dela for um ponteiro, você não poderá simplesmente copiar a estrutura para um arquivo, pois o ponteiro contém apenas um valor de endereço de memória, e é nesse endereço, que normalmente fica em outra região de memória, que os dados que você provavelmente gostaria de colocar no disco efetivamente residem.

Outro possível motivo de confusão é se você tiver dentro da estrutura dados dispostos numa forma que não coincidam com o alinhamento que seria usado pelo compilador se cada campo fosse uma variável separada. Veja o seguinte exemplo.

#include <stdio.h>

struct unaligned {
char c; // sizeof(char)==1
int i; // sizeof(int)==4 (em máquinas de 32 bits)
};

int main(void){
struct unaligned u;
printf("sizeof(struct unaligned)=%d\n", (int)sizeof u);
printf(" &u=%p\n &u.c=%p\n &u.i=%p\n", &u, &u.c, &u.i);
return 0;
}


Olhando o programa rapidamente, poderíamos ser induzidos a pensar que sizeof(struct unaligned) vale 5, pois essa é a soma dos tamanhos dos seus campos internos. No entanto, numa máquina de 32 bits, geralmente é ineficiente (e em algumas arquiteturas é simplesmente impossível) o acesso a dados dispostos em endereços que não sejam múltiplos 4 bytes (32 bits). Por isso, a maioria dos compiladores tem o comportamento default de reservar bytes a mais entre campos consecutivos de uma estrutura, a fim de garantir o alinhamento de cada campo de modo a ter o melhor desempenho. Então, não é para causar surpresa que o programa acima diga que o tamanho da estrutura é 8, e não 5, e que o endereço do campo i seja quatro bytes após o endereço do campo c, e não apenas 1.


3. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Falcão
falke

(usa Ubuntu)

Enviado em 26/05/2015 - 01:50h

paulo1205 escreveu:

Parece que você está gravando corretamente.

Se não estiver funcionando, pode ser consequência do modo como você abriu o arquivo. Pode mostrar como foi?

Aliás, como você sabe que não está funcionando? Tem como você mostrar o fread() correspondente?

Pode ser útil também conhecer maiores detalhes da sua estrutura Cliente. Se algum dos campos dentro dela for um ponteiro, você não poderá simplesmente copiar a estrutura para um arquivo, pois o ponteiro contém apenas um valor de endereço de memória, e é nesse endereço, que normalmente fica em outra região de memória, que os dados que você provavelmente gostaria de colocar no disco efetivamente residem.

Outro possível motivo de confusão é se você tiver dentro da estrutura dados dispostos numa forma que não coincidam com o alinhamento que seria usado pelo compilador se cada campo fosse uma variável separada. Veja o seguinte exemplo.

#include <stdio.h>

struct unaligned {
char c; // sizeof(char)==1
int i; // sizeof(int)==4 (em máquinas de 32 bits)
};

int main(void){
struct unaligned u;
printf("sizeof(struct unaligned)=%d\n", (int)sizeof u);
printf(" &u=%p\n &u.c=%p\n &u.i=%p\n", &u, &u.c, &u.i);
return 0;
}


Olhando o programa rapidamente, poderíamos ser induzidos a pensar que sizeof(struct unaligned) vale 5, pois essa é a soma dos tamanhos dos seus campos internos. No entanto, numa máquina de 32 bits, geralmente é ineficiente (e em algumas arquiteturas é simplesmente impossível) o acesso a dados dispostos em endereços que não sejam múltiplos 4 bytes (32 bits). Por isso, a maioria dos compiladores tem o comportamento default de reservar bytes a mais entre campos consecutivos de uma estrutura, a fim de garantir o alinhamento de cada campo de modo a ter o melhor desempenho. Então, não é para causar surpresa que o programa acima diga que o tamanho da estrutura é 8, e não 5, e que o endereço do campo i seja quatro bytes após o endereço do campo c, e não apenas 1.



Boa madrugada, amigo, obrigado pela resposta. Sim, posso mostrar, na verdade colocarei o código todo para que possa ver. Creio não estar funcionando pois tentei ler a estrutura e não consegui, acho que não sei como colocar o "printf" ou o "puts" para escrever o que eu quero, pode ser erro de sintaxe, enfim, abaixo está o cód.

#include <stdio.h>
#include <stdlib.h>
typedef struct Cliente{ //estrutura que usei para gravar
char nome[30];
int dias;
char endereco[101];
float conta;
}Cliente;

typedef struct Leitura{ //criei outra estrutura para leitura
char lnome[30];
int ldias;
char lendereco[101];
float lconta;
}Leitura;

int main(){
int i, opcao;
Cliente ficha[3];
Leitura lficha[3];
do{
do{
printf("++++++++++++++++ Registro de clientes +++++++++++++++\n\n");
printf("[1] Registro de cliente\n");
printf("[2] Leitura de cliente\n");
printf("[0] Sair\n");
fflush(stdin);
printf("Opcao: ");
scanf("%d", &opcao);
}while(opcao!=1&&opcao!=2&&opcao!=0);

if(opcao==1){
FILE *ptarq = fopen("binario.bin", "wb"); //abrindo arquivo para escrita
for(i=1;i<=3;i++){
system("pause");
system("cls");

fflush(stdin);
printf("Digite o nome do cliente: ");
gets (ficha[i].nome);
printf("Digite o numero de dias na pousada: ");
scanf("%d", &ficha[i].dias);
fflush(stdin);
printf("Digite o seu endereco: ");
gets(ficha[i].endereco);

if(ficha[i].dias<10){
ficha[i].conta=((ficha[i].dias*100)+15);
}
else{
ficha[i].conta=((ficha[i].dias*100)+8);
}

printf("Total a ser pago: R$%.2f\n", ficha[i].conta);
system("pause");
system("cls");
fwrite(&ficha, sizeof(Cliente), 1, ptarq); //fechamento
fclose(ptarq);
}
}
else{
if(opcao==2){ //aqui tento utilizar outra struct para leitura
FILE *leitura=fopen("binario.bin", "rb");
fread(&lficha, sizeof(Leitura), 1, leitura);
printf("%d", lficha[1].ldias); //tentei testar para ver se funcionava lendo o n de dias
}
}
}while(opcao==5); //deixei aqui pra colocar depois para funcionar aueahsdae
}



4. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 26/05/2015 - 10:39h

Algumas observações:

* Você não precisa ter duas estruturas com formato idêntico, mas com nomes diferentes. O mesmo tipo de dados serve tanto para a leitura quanto para a escrita.

* Em C e C++, o primeiro índice de um array é sempre 0. Isso implica que para um array com N elementos, o último índice válido é necessariamente N-1. Portanto, quando você faz um laço de repetição variando o índice de 1 a 3, você pula o primeiro elemento, cujo índice é 0, e extrapola o limite declarado do tamanho do array ao gravar um quarto elemento (com índice 3).

* Existe uma inconsistência entre os parâmetros que você usa no momento de gravar em disco, que infelizmente o compilador não tem como detetar.

O primeiro parâmetro de fwrite() recebe um ponteiro para dados de um tipo X. O segundo argumento deve combinar com o primeiro da seguinte maneira: como o dado apontado é do tipo X, então o segundo argumento tem de ser o tamanho do tipo X. O terceiro argumento informa quantos elementos adjacentes desse tipo X devem ser gravados, começando a contar tais elementos pela posição de memória indicada pelo ponteiro passado no primeiro argumento. O quarto parâmetro é fácil de entender, pois é o ponteiro que indica o arquivo

Seu erro é que você passa um argumento do tipo “ponteiro para array com três elementos do tipo Cliente” (ficha, sozinho, é uma referência para o primeiro elemento, mas &ficha, que é o que você escreveu, é uma referência para o array inteiro) e, no entanto, passa como segundo argumento o tamanho de um “Cliente”, e não o de um “array com três elementos do tipo Cliente”, que seria o correspondente. Por fim, o terceiro argumento completa o uso inconsistente, pois ele manda gravar uma quantidade de dados que é múltipla do tamanho indicado no segundo argumento, embora ele não concorde com o tipo do primeiro argumento.

Como você colocou a gravação dentro do mesmo laço de repetição em que faz a leitura dos dados, eu diria que você quer gravar o registro do cliente que acabou de ler. Como tais dados estão em ficha[i], você deve dizer o seguinte

fwrite(&ficha[i ], sizeof(Cliente), 1, ptarq) 


Tenho minhas dúvidas de ser você deveria usar um array para os dados de leitura, uma vez que apenas grava um elemento de cada vez em disco, assim que termina de ler seus dados. Depois, você não usa mais o array como uma coleção de clientes. Haveria uma justificativa se ao menos você terminasse de ler o array e, já fora do laço de repetição usado para a digitação dos dados, gravasse o array inteiro de uma só vez, com uma só chamada a fwrite(), usando uma das formas abaixo (ambas mantêm a coerência entre todos os argumentos).

/*
1º arg: endereço do (i.e. ponteiro para) 1º elemento do array
2º arg: tamanho de cada elemento (==tamanho do primeiro elemento)
3º arg: nº de elementos do array (tamanho total/tamanho de elemento --
só pode ser usado com arrays; se fosse um ponteiro, você seria
obrigado a saber o nº exato de elementos)
4º arg: ponteiro do arquivo
*/
fwrite(ficha, sizeof *ficha, sizeof ficha/sizeof *ficha, ptarq);


/*
1º arg: endereço do (i.e. ponteiro para) o array inteiro
2º arg: tamanho do array inteiro
3º arg: quantidade de arrays que estamos gravando (no nosso caso
esse valor obviamente é 1)
4º arg: ponteiro do arquivo
*/
fwrite(&ficha, sizeof ficha, 1, ptarq);


Apesar de o código que você fez misturar tipos de dados nos diferentes argumentos de fwrite(), ele acaba gravando o primeiro elemento três vezes, pois o valor absoluto do endereço do array como um todo coincide com o valor absoluto do endereço do primeiro elemento, ainda que os tipos desses dois endereços sejam diferentes. No entanto, como você errou nos valores dos índices durante a leitura, o elemento que é gravado três tem valores indefinidos.

* Você comete erro análogo de tipos ao fazer a leitura de dados do arquivo. Não dá para ter certeza de se você quis ler elementos consecutivos para todo o array, como sugere o primeiro argumento, ou apenas o primeiro elemento, como sugerem o segundo e o terceiro. Por causa da coincidência entre os valores dos endereços do array como um todo e do seu primeiro elemento (embora os tipos sejam diferentes), o efeito final, embora mal expressado, seria o de ler dados apenas para o primeiro elemento.

Entretanto, você de novo erra no índice na hora de imprimir. Os dados lidos vão para o primeiro elemento (índice 0), mas você imprime dados do segundo (índice 1), que não recebeu valores durante a operação de leitura.


5. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Falcão
falke

(usa Ubuntu)

Enviado em 27/05/2015 - 01:14h

paulo1205 escreveu...


Paulo, não tenho palavras para agradecê-lo, creio que entendi boa parte do que entendeu e realmente sou grato por isso. Estou no trabalho e o antívirus aqui não me permite abrir o .exe em que irei trabalhar, mas chegando em casa tentarei fazer as modificações propostas e ver se realmente entendi.
Só esclarecendo: minha intenção é gravar toda a estrutura de dados, assim como também lê-la, o que me gera uma pequena dúvida, sem querer importuno, afinal, acaba de me dar uma aula. Ao executar o comando para que o programa leia o arquivo binário criado eu preciso que isso seja mostrado na tela, como fazer isto? Preciso criar um printf, ou puts para cada uma das variáveis(ex: ficha.nome, ficha.dias, ficha.endereco), ou há algum comando em que o programa escreva tudo?

Novamente, muito obrigado!






6. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 27/05/2015 - 08:36h

A biblioteca padrão do C não oferece nenhum mecanismo para imprimir estruturas definidas pelo usuário. O único tipo composto que a biblioteca padrão trata de modo relativamente consistente em operações de I/O é array de caracteres, quando tais arrays representam strings de texto.

Assim sendo, você é obrigado, sim, a tratar campo por campo da sua estrutura.

Nada o impede, porém, de criar suas próprias funções para imprimir e para ler Clientes, e de usá-las tantas vezes quanto precisar.


7. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Falcão
falke

(usa Ubuntu)

Enviado em 28/05/2015 - 16:02h

paulo1205 escreveu:


Paulo, me perdoe pelo incomodo, mas se possível, me dê uma luz:

Eu segui o que você falou e o que minha professora havia dito. Tirei duas estruturas, já que não havia necessidade, ajeitei a estrutura de repetição, pois foi um erro bobo, mas não consigo ainda fazer com que meu programa funcione direito. Na verdade eu consigo fazer com que ele grave os dados do primeiro Cliente(nome, dias, total), e consigo ler perfeitamente ele, mas o resta eu não consigo, aparentemente não estou gravando direito, pois ao ler o Cliente[2] e o Cliente[1] ele me dá respostas nada a ver. Caso possa analisar o código está abaixo:

#include <stdio.h>
#include <stdlib.h>
typedef struct Cliente{ //estrutura que usei para gravar
char nome[30];
int dias;
char endereco[101];
float conta;
}Cliente;

int main(){
int i, opcao;
Cliente ficha[2];
do{
do{
printf("++++++++++++++++ Registro de clientes +++++++++++++++\n\n");
printf("[1] Registro de cliente\n");
printf("[2] Leitura de cliente\n");
printf("[0] Sair\n");
fflush(stdin);
printf("Opcao: ");
scanf("%d", &opcao);
}while(opcao!=1&&opcao!=2&&opcao!=0);

if(opcao==1){
FILE *ptarq = fopen("binario.bin", "wb"); //abrindo arquivo para escrita
for(i=0;i<=2;i++){
system("pause");
system("cls");
fflush(stdin); //coletando informações
printf("Digite o nome do cliente: ");
gets (ficha[i].nome);
printf("Digite o numero de dias na pousada: ");
scanf("%d", &ficha[i].dias);
fflush(stdin);
printf("Digite o seu endereco: ");
gets(ficha[i].endereco);

if(ficha[i].dias<10){
ficha[i].conta=((ficha[i].dias*100)+15);
}
else{
ficha[i].conta=((ficha[i].dias*100)+8);
}

printf("Total a ser pago: R$%.2f\n", ficha[i].conta);
fwrite(&ficha, sizeof(Cliente), 1, ptarq);

}
fclose(ptarq);
}
else{
if(opcao==2){ //tentativa de leitura do arquivo binario
FILE *ptarq=fopen("binario.bin", "rb");
fread(&ficha, sizeof(Cliente), 1, ptarq);
for(i=0;i<=2;i++){
puts(ficha[i].nome);
printf("%d\n", ficha[i].dias);
puts(ficha[i].endereco);
printf("%.2f\n", ficha[i].conta);
system("pause");
}
fclose(ptarq);
}
}
}while(opcao==5);
}


PS: Ajeitei a linha de código na estrutura de repetição, desci o "fread" e funcionou, aleluia, MUITO OBRIGADO, mesmo, agora o programa tá dando erro na hora de fechá-lo, vou garimpar aqui pra ver o que faço aheuihaids. Caso alguém veja no futuro, fiz o seguinte:


if(opcao==2){ //tentativa de leitura do arquivo binario
FILE *ptarq=fopen("binario.bin", "rb");
for(i=0;i<=2;i++){
fread(&ficha[i], sizeof(Cliente), 1, ptarq);
puts(ficha[i].nome);
printf("%d\n", ficha[i].dias);
puts(ficha[i].endereco);
printf("%.2f\n", ficha[i].conta); //tentei testar para ver se funcionava lendo o n de dias
system("pause");


Assim como de certa forma o Paulo falou, sigam o rapaz.




8. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 29/05/2015 - 17:00h

falke escreveu:

Paulo, me perdoe pelo incomodo, mas se possível, me dê uma luz:

Eu segui o que você falou e o que minha professora havia dito. Tirei duas estruturas, já que não havia necessidade, ajeitei a estrutura de repetição, pois foi um erro bobo, mas não consigo ainda fazer com que meu programa funcione direito. Na verdade eu consigo fazer com que ele grave os dados do primeiro Cliente(nome, dias, total), e consigo ler perfeitamente ele, mas o resta eu não consigo, aparentemente não estou gravando direito, pois ao ler o Cliente[2] e o Cliente[1] ele me dá respostas nada a ver. Caso possa analisar o código está abaixo:

#include <stdio.h>
#include <stdlib.h>
typedef struct Cliente{ //estrutura que usei para gravar
char nome[30];
int dias;
char endereco[101];
float conta;
}Cliente;


O código até aqui não tem nenhum erro, mas permita-me dar uma dica que se aplica a todo o código e a todo código (um artigo definido faz toda a diferença): procure espaçar e alinhar seu código de uma forma que facilite a leitura. À semelhança do que acontece numa redação quando você usa encerra um período com um ponto final ou quando muda de parágrafo, procure pular linhas quando o código do programa passa da realização de uma operação para outra que não seja diretamente relacionada à anterior. Alinhe também o conteúdo de modo a facilitar a visão de o que está subordinado a quê, ou aquilo que compõe o que é composto.

Veja como eu aconselho a reescrever as primeiras linhas do programa.

#include <stdio.h>
#include <stdlib.h>
/* Terminei a seção de includes. Eu costumo pular duas linhas entre seções distintas. */


/*
Comentário dizendo para quê serve struct Cliente, e o porquê de eu ter
usado um typedef para ele.
*/
typedef struct Cliente{
/* O membros são subordinados à estrutura
char nome[30];
int dias;
char endereco[101];
float conta;
} Cliente;


Eu tenho uma crítica ao uso de typedefs por mera conveniência. Creio que quando o usuário do tipo tiver de saber que se trata de uma estrutura, o que normalmente é quando tem de manipular seus campos de forma individualizada, convém deixar (ou obrigar a) que ele escreva a forma “struct nome_da_estrutura”. Só defendo que se use typedef quando se quiser evitar a manipulação de campos internos pelo usuário.

Acho que essa minha preferência pessoal reflete o que se encontra na biblioteca padrão do C. Por exemplo, é esperado que o usuário manipule separadamente os campos da struct tm (em <time.h>, e que serve para se obter uma representação de data e hora) ou da struct div_t (em <stdlib.h>, e que serve para representar o tipo de retorno da função div(), contendo campos que trazem ao mesmo tempo o quociente e o resto de uma divisão entre dois inteiros). Em contraste com isso, os dados internos do tipo FILE (definido em <stdio.h> geralmente como estrutura, mas uma implementação criativa poderia usar outra coisa, como array de bytes ou de inteiros) não são expostos para o usuário, a fim evitar a tentação de manipulá-los diretamente e, com isso, criar uma série de dependências de um ambiente específico, que dificulta reaproveitar o código num ambiente diferente (ou mesmo numa evolução futura do ambiente original).

Além da biblioteca padrão do C, várias outras bibliotecas de uso comum se alinham mais ou menos com essa prática de explicitar a estrutura do que deve ser tratado em nível de campos e esconder com typedefs o que o programador pode ou deve tratar como objeto fechado, aos cuidados da biblioteca feita especificamente para manipulá-lo.

int main(){
int i, opcao;
Cliente ficha[2];


Aqui você disse que o array ficha tem apenas dois elementos. Isso está em desacordo com a faixa que você usa, mais abaixo, para os índices, que você varia entre 0 e 2 (três valores).

do{
do{
printf("++++++++++++++++ Registro de clientes +++++++++++++++\n\n");
printf("[1] Registro de cliente\n");
printf("[2] Leitura de cliente\n");
printf("[0] Sair\n");
fflush(stdin);
printf("Opcao: ");
scanf("%d", &opcao);
}while(opcao!=1&&opcao!=2&&opcao!=0);

if(opcao==1){
FILE *ptarq = fopen("binario.bin", "wb"); //abrindo arquivo para escrita
for(i=0;i<=2;i++){


Viu? i assume, a cada iteração, os valores 0, 1 e 2. Logo você usa três elementos, embora só tenha alocado espaço para dois.

                system("pause");
system("cls");
fflush(stdin); //coletando informações
printf("Digite o nome do cliente: ");


Você poderia ajudar o usuário, dando uma ideia de quantos clientes ele já cadastrou. Veja o exemplo.

printf("Digite o nome do %dº cliente: ", i+1); 


                gets (ficha[i ].nome);
printf("Digite o numero de dias na pousada: ");
scanf("%d", &ficha[i ].dias);
fflush(stdin);
printf("Digite o seu endereco: ");
gets(ficha[i ].endereco);

if(ficha[i ].dias<10){
ficha[i ].conta=((ficha[i ].dias*100)+15);


Todos esses parênteses no cálculo da expressão podem ser omitidos.

Mas algo mais do que isso. Do ponto de vista de arquitetura de dados, se o valor da conta depende da quantidade de dias por uma fórmula fixa e conhecida, é redundante ter as duas como membros da estrutura e ou ocupando espaço em disco.

Mesmo que você tenha um componente variável e nem sempre presente, como um desconto ou uma multa, seria interessante você colocar essa informação explicitamente na estrutura (por exemplo, se o cliente pagou a menos do que seria de esperar, é mais útil saber que é porque ele teve um desconto, e não por uma arbitrariedade ou erro qualquer).

                }
else{
ficha[i ].conta=((ficha[i ].dias*100)+8);


Mesma observação quanto aos parênteses e quanto à redundância.

                }

printf("Total a ser pago: R$%.2f\n", ficha[i ].conta);
fwrite(&ficha, sizeof(Cliente), 1, ptarq);


Você simplesmente não corrigiu a chamada a fwrite(), pois continua com um ponteiro para o array inteiro (cujo endereço coincide com o do primeiro elemento), mas com a especificação de tamanho de um elemento só. Como esse fwrite() está dentro do laço de repetição, você grava o primeiro elemento três vezes.



}
fclose(ptarq);
}
else{
if(opcao==2){ //tentativa de leitura do arquivo binario
FILE *ptarq=fopen("binario.bin", "rb");
fread(&ficha, sizeof(Cliente), 1, ptarq);


Aqui você cometeu mesmo erro de não correspondência entre tipos dos argumentos, mas com um efeito final diferente. Como a chamada a fread() está fora do laço de repetição, parece que você quis ler o array inteiro de uma só vez. No entanto, você informou um tamanho que corresponde a apenas um elemento do array. O efeito final é que você lê apenas o primeiro elemento, e os dois outros ficam inalterados (possivelmente indefinidos).

Um observação adicional, que vale tanto para a escrita quanto para a leitura é que você não testa os valores devolvidos pelas funções. Num mundo ideal, erros de leitura e de escrita nunca ocorrem, mas você deve se preparar para o mundo real, em que é possível que uma operação de I/O tenha sucesso parcial ou falhe completamente. Para saber se tudo correu bem, você deve comparar o valor retornado pela função com o valor do terceiro argumento. Veja detalhes na documentação das funções fread() e fwrite() (por exemplo, em http://netbsd.gw.com/cgi-bin/man-cgi?fread++NetBSD-current).


for(i=0;i<=2;i++){
puts(ficha[i ].nome);
printf("%d\n", ficha[i ].dias);
puts(ficha[i ].endereco);
printf("%.2f\n", ficha[i ].conta);
system("pause");
}
fclose(ptarq);
}
}
}while(opcao==5);


Veja como esse alinhamento de código está confuso.

} 


Em C, você deve dizer explicitamente qual o valor de retorno da função main() antes de ela chegar ao final. Isso pode ser feito por meio de um comando “return valor;” (minha preferência) ou por meio de uma chamada “exit(valor);”, mas tem de ser feito. E, por convenção, um valor de retorno igual a zero indica sucesso, e outro valor indica algum tipo de erro.

(Em C++, o comando return antes do fim de main() é opcional, e o compilador assume um return 0;implícito se ele não estiver presente. Eu, particularmente, não gosto muito disso, pois cria uma inconsistência entre a função main() e todas as outras funções que retornam algum valor, pois essa opção só existe para main().)

PS: Ajeitei a linha de código na estrutura de repetição, desci o "fread" e funcionou, aleluia, MUITO OBRIGADO, mesmo, agora o programa tá dando erro na hora de fechá-lo, vou garimpar aqui pra ver o que faço aheuihaids. Caso alguém veja no futuro, fiz o seguinte:


if(opcao==2){ //tentativa de leitura do arquivo binario
FILE *ptarq=fopen("binario.bin", "rb");
for(j=0;j<=2;j++){
fread(&ficha[j], sizeof(Cliente), 1, ptarq);
puts(ficha[j].nome);
printf("%d\n", ficha[j].dias);
puts(ficha[j].endereco);
printf("%.2f\n", ficha[j].conta); //tentei testar para ver se funcionava lendo o n de dias
system("pause");


(Troquei o i no bloco acima por j, mas apenas para evitar os problemas de formatação do fórum, que usa “[i]” para indicar texto em itálicos.)

Ah, então o código anterior não era a versão final? Então não precisava tê-lo publicado.

Bom, o erro no final é fácil de explicar: quando você gravou o terceiro elemento num array declarado para conter apenas dois elementos, essa operação sobrescreveu memória pertencente a outras variáveis e estruturas de controle do programa, incluindo a informação de o que fazer (ou melhor, o endereço para onde o programa deveria retornar) após o termino da execução da função main().


9. Re: Gravar dados de uma struct em arquivo binário na linguagem C.

Falcão
falke

(usa Ubuntu)

Enviado em 06/06/2015 - 18:56h

paulo1205 escreveu:


Paulo, perdão o hiatus, estive em semana de provas, trabalhos e etc mas não poderia deixar de lhe responder. Muito obrigado pela a sua ajuda e levarei em consideração todos os seus conselhos, muito grato.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts