• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

smt

Estruturas e ficheiros

12 mensagens neste tópico

Olá a todos! Eu tou com problemas sérios em relação a estruturas em C e ficheiros.

Dúvidas:

1- Aki dou o exemplo duma struct Pessoa com um só atributo(pa facilitar), embora vá ter muitas mais variáveis;a minha dúvida é: ñ existe uma maneira simples(recorrendo a ponteiros p.ex.) de  modificar os atributos duma struct, sem recorrer a variáveis auxiliares?O professor disse-me k assim resolvia o problema, mas caramba se tiver 100 atributos, tenho k recorrer a 100 auxiliares cada x k pergunto ao utilizador/modifico? N tem mta logica...digo eu! :eek:

2- Aqui faço a escrita da struct directamente pro file, em modo binário( n sei se está bem); isto é ,pa no futuro, vir a gravar a estrutura mais complexa directamente no ficheiro;só ko meu problema aqui está tb relacionado com a dúvida anterior;tenho uma struct com N atributos, e kero pedir ao utilizador e escreve-los no file.Como faço isso?

P.S.: Só me interessa trabalhar com ficheiros binários.

typedef struct{
char nome[10];
}Pessoa;

int main()
{
FILE *fp;
Pessoa person;
char name[10]="";//auxiliar para conter nome
printf("nome: ");
scanf("%s", &name);
strcpy(person.nome,name);
printf("nome da pessoa:%s\n",&person.nome);

   
    fp = fopen("ficheiro1.txt","a+b");//abre ficheiro binário para escrita(append)
    
    if(!feof(fp))
    {
      fwrite (&person, sizeof(Pessoa), 1, fp); 
    }
    fclose(fp);
    
    // Ler do mesmo ficheiro o que foi escrito
    fp = fopen("ficheiro1.txt","r+b");//abre ficheiro binário para leitura
    while(!feof(fp)){
    	fread (&person, sizeof(Pessoa), 1, fp);	
    }
    printf("nome da pessoa:%s\n",&person);
    fclose(fp);
}

Agradeço resposta rapida! E desculpem, mas sou uma noobie nisto

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se não me engano ao fazeres

fwrite (&person, sizeof(Pessoa), 1, fp); 

Estás a gravar no ficheiro o endereço da struct experimenta fazer

fwrite ((char *)person, sizeof(*Pessoa), 1, fp);

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

quanto à questão da variável auxiliar, acho que podias colocar directamente

scanf("%s", &person.nome)

e deixa de precisar da variável auxiliar.

na segunda questão, não percebi a tua dúvida... o código que tens parece-me que está correcto e vai continuar a funcionar da mesma maneira depois de adicionares mais atributos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Porque é que estão a utilizar & antes de "person.nome" tanto na leitura como na escrita?

person.nome já é um apontador, não necessida de & atrás.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O & foi lapso meu, embora o compilador n revele erros, temos de confiar no programador

Btw a instrução fwrite ((char *)person, sizeof(*Pessoa), 1, fp); não funciona neste caso...

Basicamente fiz o scanf directamente para a variável da struct  ( scanf("%s",person.nome) )escrevi e li do ficheiro.

Testei com e sem variável auxiliar, e deu-me o mm resultados nos ficheiros criados.Tb leu bem.

Bem, depois tenho d testar com a struct completa, até porque vai meter inteiros, que eu depois vou ter de utilizar e manipular.

Alguma sugestão/reparo

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem, testei este código para TENTAR gravar num file o conteúdo duma estrutura com apenas 2 atributos do tipo char que precisam de ser limitados. Contudo, o código funcionou mt bem à 1ª, 2ª e dps...simplesmenten funcionou.Escrevam por exemplo:

nome: joao m

apelido:costa

Ele imprime-> O que esta em ficheiro:joao

Ou seja,"come" sempre o ultimo caracter do nome, descarta o apelido, quando ao inicio n fazia isso.Por isso, ou eu tou com problemas em alocar memória utilizado estruturas ou então vou ter de escrever atributo por atributo :eek:, como li algures:

However, unlike normal arrays, the compiler doesn't know how much room you've got stored in that pointer (if any). Therefore, you cannot use a simple fwrite to write a structure with a pointer in it. You must take care of writing the structure, member by member, yourself.

Alg me ajuda?Posso ter erros graves, mas n colocaria aqui a questão se n estivesse mt desesperada! :down:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct{
char nome[10];
char apelido[10];
}Pessoa;

int leFicheiro(FILE *filepointer, Pessoa pessoa);

int main()
{
FILE *fp;
Pessoa person;
printf("nome: ");
scanf("%10[^\n]s",&person.nome);
fflush(stdin);
	if (person.nome[strlen(person.nome)-1] == '\n');
		person.nome[strlen(person.nome)-1]='\0';
printf("apelido: ");
scanf("%10[^\n]s",&person.apelido);
fflush(stdin);
	if (person.apelido[strlen(person.apelido)-1] == '\n')
		person.apelido[strlen(person.apelido)-1]='\0';


    fp = fopen("ficheiro2.txt","a+b");//abre ficheiro binário para escrita(append)
    
    if(!feof(fp))
    {
      fwrite (&person, sizeof(Pessoa),1, fp); 
    }
    fclose(fp);
    
    leFicheiro(fp,person);
  
}

int leFicheiro(FILE *fp, Pessoa pessoa){
/* Lê um ficheiro por completo*/

  long lSize;
  char *buffer;// cada apontador de char ocupa 4 bytes
  size_t result;

  fp = fopen ( "ficheiro2.txt" , "rb" );
  if (fp==NULL) {fputs ("File error",stderr); exit (1);}

  // para obter o tamanho do ficheiro:
  fseek (fp , 0 , SEEK_END);
  lSize = ftell (fp);
  rewind (fp);	
  //alocar memória para todo o conteúdo do ficheiro
  buffer = (char*) malloc (sizeof(Pessoa)*lSize);
  if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

  // copiar o ficheiro para o buffer
  result = fread (buffer,1,lSize,fp);
  if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

  /*o conteúdo do ficheiro encontra-se agora no buffer em memória. */
  // finalizar
  printf("O que esta em ficheiro:%s ",buffer);
  fclose (fp);
  free (buffer);
  return 0;

}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

o problema de comer o último caracter está nestas linhas:

if (person.nome[strlen(person.nome)-1] == '\n');

  person.nome[strlen(person.nome)-1]='\0';

no final do if tens um ; a mais, ou seja, tu é que estavas a comer o último carater.

quanto à função de leitura, experimenta assim:

int leFicheiro(FILE *fp){
  Pessoa p;
  size_t result;

  fp = fopen ( "ficheiro2.txt" , "rb" );
  if (fp==NULL) {fputs ("File error",stderr); exit (1);}

  fread (&p,1,sizeof(Pessoa),fp);

  printf("O que esta em ficheiro:%s %s",p.nome,p.apelido);
  fclose (fp);
  return 0;
}

porque razão não estavas a ler o conteúdo do ficheiro para uma varíável do tipo Pessoa?

removi algumas verificações de erros que deves voltar a colocar...

PS: embora não use muito isso, acho que nos scanfs é só "%10[^\n]" (o 's' está a mais).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tks, realmente akilo de comer o caracter foi distracção  :) ( se todos os males fossem desses, né?)

Usei o k me disseste e deu, embora o size_t result n esteja la a fazer nada...

E sim, tens de usar "%10[^\n]s" se nao ele nao reconhece como string. Pelo menos testei sem "s", e dps akilo imprimia uma data de "caracteres nao identificáveis".

Btw, continuo com a mesma duvida geral: se tiver 100 atributos numa estrutura tenho k imprimir dps sempre p.nome, p.apelido,p.xpto,...por ai fora? N há uma maneira mais geral para resolver isto? Eu ando aki as voltas com isso, mas se nao der, fica para o final da implementação. 1º pôr a funcionar, depois condensar/optimizar código.

Obrigada pela ajuda preciosa  :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Estás-te a referir aos printfs?

Existe sempre a alternativa de criar um vector com a informação, neste caso um vector de strings, e mandar imprimir tudo de uma vez usando um "for". Tirando isso, não há nada a fazer.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Exacto, estou-me a referir aos printfs.Porque, se tudo correr bem, ao escrever para ficheiro ele escreve-me os atributos todos, que é que interessa.O printf foi só para testar e por curiosidade tb. Eu escrevo a minha struct dentro do ficheiro, com n atributos.Quando faço os printfs é no leFicheiro, que chamo no main dando-lhe o ponteiro fp como argumento.

int leFicheiro(FILE *fp){
  Pessoa p;

  fp = fopen ( "ficheiro2.txt" , "rb" );
  while(!feof(fp)){
	fread (&p, sizeof(Pessoa), 1, fp);	
  }
  printf("O que esta em ficheiro:%s %s",p.nome,p.apelido); // ele está a ler directamente do file, certo?
  fclose (fp);
  return 0;
}

Outra coisa: o que vai para dentro do ficheiro, se não me engano, vai sem espaços.Isto é, se eu ali no printf não deixasse um space entre as strings que vou receber, ele imprimia tudo seguido, o que significa que, em ficheiro, os atributos da Pessoa estão todos seguidos,sem espaços.Como é que eu posso manipular a forma como isso é escrito dentro do file? Isto é, eu faço um fwrite da  estrutura mas depois quero que os atributos fiquem separados por espaço, tab ou outra coisa qualquer.Existe maneira de fazer isso?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

podes guardar os ficheiros em formato de texto, mas neste caso só te complica a tarefa (para além de ser menos eficiente)... embora já podesses controlar isso dos espaços.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Uhm, não sabia.Pois, mas tenho mesmo de trabalhar com ficheiros binários, porque também vai facilitar depois na implementação de outras funções.Bem, se surgir alguma dúvida entretanto, eu posto aqui, porque já vi que structs e files (que mexem quase sempre com ponteiros)são dúvidas gerais do ppl. Tks mais uma x  ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora