Odczyt struktury z pliku - jak to zrobić?

0

Mam binarny plik baza.bdf. Mam do niego zapisać strukturę:

struct baza                           
{
unsigned long int id;                
 char imie[30];                      
 char nazwisko[60];                  
 }rekord;

A zapisuję ją tak:

int main()
 {
 baza x;
 char z;
 FILE *plik;
  if((plik=fopen("c:\\baza.dbt","r+b"))==0)
  {
   plik=fopen("c:\\baza.dbt","w+b");
   fclose(plik);
   }
  else
  while(z!=27)
  {
  menu();
  z=getche();
  switch(z)
  {
   case'1':               
   {
    plik=(fopen("c:\\baza.dbt","r+b"));
    puts("Wpisz numer id");
    scanf("%d",&rekord.id);
    fprintf(plik,"%d",rekord.id);
    puts("Wpisz imie");
    scanf("%s",&rekord.imie);
    fprintf(plik,"%s",rekord.imie);
    puts("Wpisz nazwisko");
    scanf("%s",&rekord.nazwisko);
    fprintf(plik,"%s",rekord.nazwisko);
    getch();
    fclose(plik);
    break;
    }

Tylko mam takie problemy:

  1. Jak zrobić, żeby mi się zapisywało kilka rekordów obok siebie. Mi zapisuje się jeden na drugim.
  2. Jak odczytać później te rekordy. Ja napisałem to tak (ale wychodzą mi dziwne rzeczy, a do tego nie wiem jak odczytać unsigned long int, bo %d chyba tego nie odczytuje):
 case'2':
   {
    plik=(fopen("c:\\baza.dbt","r+b"));
    fread(&x,sizeof(rekord),1,plik);
    printf("%s",x.imie);
    printf("%s",x.nazwisko);
    getch();
    fclose(plik);
    break;
    }

Dzięki za jakąkolwiek pomoc !!

//kod umieszczaj w tagach! - m.M

0

Ad 1: Zapisuje sie jedno na drugim, bo w miedzyczasie zamykasz i ponownie otwierasz plik w trybie nadpisywania.
Jesli tego nie bedziesz robil, to zapisze sie jedno za drugim. Ewentualnie uzyj trybu dopisywania tj. "a+".

Ad 2: unsigned long int odczytuje sie %ul. Zapisuje sie tez %ul a nie %d.
Odczytanie 30 znakow tekstu z pliku robi sie poprzez fscanf(plik, "%30c", wskaznik_do_lancucha).

0

Po pierwsze musisz stworzyc jakis naglowek w ktorym bedziesz mial ilosc rekordow. Zapisuj wszytsko za pomoca fwrite i odczytuj za pomoca fread (cale struktury od razu), do skakania w pliku do odpowiednich rekordow uzyj fseek wtedy bedziesz mogl odczytywac i zapisywac konkretny rekord.

0

Czy ten nagłówek, to powinno być coś takiego, jak kolejny numer rekordu? Np:

struct baza
{
int nrkolejnyrekordu;
//.....resztapólrekordu;
}

0

Hmm
struct header
{
long int rekords;
long int rekord_size;
}

a dalej w pliku leca twoje rekordy, aby skoczyc pod dany rekord to uzyj fseek a pozycje obliczasz z :
sizeof(struct header) + sizeof(struct rekord) * numer_rekordu;

0

Ej namieszaliście chłopakowi. Po co w ogole w pliku zapisywać ilośc rekordów, skoro można to sobie obliczyć z jego długości ?

No nic, prosta klasa + demko bazy danych:

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

typedef unsigned long ulong;

class f_base{
  public:

    f_base();
    ~f_base();

    int  open(char* file,ulong id);  // id - file header
    int  create(char* file,ulong id,unsigned itemsize);
    void close();
    void flush();
    int  get(void* buf,long pos=0,int whence=SEEK_CUR);
    int  put(void* buf,long pos=0,int whence=SEEK_CUR);
    int  del(long count,long pos=0,int whence=SEEK_CUR);
    int  setpos(long newpos,int whence=SEEK_SET);
    long getpos();
    long getsize();

  protected:
    unsigned isize;
    long     curpos;
    long     items;
    FILE*    bf;
};

f_base::f_base(){
  bf=0;
  curpos=0;
  isize=0;
  items=0;
}

f_base::~f_base(){
  close();
}

int f_base::open(char* file,ulong id){
  FILE* f=fopen(file,"r+b");
  if(!f)return 0;
  long fl=filelength(fileno(f));
  if(fl<8)goto error;
  ulong d;
  if(fread(&d,4,1,f)^1)goto error;
  if(d^id)goto error;
  ulong is;                           // for 16 & 32 bit compilers compatybility
  if(fread(&is,4,1,f)^1)goto error;
  items=(fl-8)/is;
  isize=unsigned(is);                 // for 16 & 32 bit compilers compatybility
  curpos=0;
  bf=f;
  return 1;
  error:
  fclose(f);
  return 0;
}

int f_base::create(char* file,ulong id,unsigned itemsize){
  FILE* f=fopen(file,"w+b");
  if(!f)return 0;
  ulong is=itemsize;                  // for 16 & 32 bit compilers compatybility
  if(fwrite(&id,4,1,f)^1)goto error;
  if(fwrite(&is,4,1,f)^1)goto error;
  isize=itemsize;
  curpos=0;
  items=0;
  bf=f;
  return 1;
  error:
  fclose(f);
  return 0;
}

void f_base::close(){
  if(bf)fclose(bf);
  bf=0;
  curpos=0;
  isize=0;
  items=0;
}

void f_base::flush(){
  if(bf)fflush(bf);
}

int f_base::get(void* buf,long pos,int whence){
  long p;
  switch(whence){
    case SEEK_END:p=items+pos;break;
    case SEEK_CUR:p=curpos+pos;break;
    default      :p=pos;
  }
  if(p<0 || p>items)return 0;
  if(fseek(bf,(p*isize)+8,SEEK_SET))return 0;
  if(fread(buf,isize,1,bf)^1)return 0;
  (curpos=p)++;
  return 1;
}

int f_base::put(void* buf,long pos,int whence){
  long p;
  switch(whence){
    case SEEK_END:p=items+pos;break;
    case SEEK_CUR:p=curpos+pos;break;
    default      :p=pos;
  }
  if(p<0 || p>items)return 0;
  if(fseek(bf,(p*isize)+8,SEEK_SET))return 0;
  if(fwrite(buf,isize,1,bf)^1)return 0;
  (curpos=p)++;
  if(curpos>items)items=curpos;
  return 1;
}

int f_base::del(long count,long pos,int whence){
  long p;
  switch(whence){
    case SEEK_END:p=items+pos;break;
    case SEEK_CUR:p=curpos+pos;break;
    default      :p=pos;
  }
  void* b=malloc(isize);
  if(!b)return 0;
  while(p+count<items){
    if(!get(b,p+count,SEEK_SET))goto error;
    if(!put(b,p++,SEEK_SET))goto error;
  }
  free(b);
  if(chsize(fileno(bf),(items-count)*isize+8))return 0;
  items-=count;
  return 1;
  error:
  free(b);
  return 0;
}

int f_base::setpos(long newpos,int whence){
  long p;
  switch(whence){
    case SEEK_END:p=items+newpos;break;
    case SEEK_CUR:p=curpos+newpos;break;
    default      :p=newpos;
  }
  if(p<0 || p>items)return 0;
  if(fseek(bf,(p*isize)+8,SEEK_SET))return 0;
  curpos=p;
  return 1;
}

long f_base::getpos(){
  return curpos;
}

long f_base::getsize(){
  return items;
}


struct adr{
  char imi[20];
  char naz[30];
  char tel[20];
} d;

main(){
  char* id="adr";
  f_base f;
  f.create("c:\\adr.dat",*((ulong*)id),sizeof(adr));
  printf("\n\nilosc elementow : %ld\n",f.getsize());
  printf("pozycja : %ld\n",f.getpos());
  strcpy(d.imi,"koziolek");
  strcpy(d.naz,"matolek");
  strcpy(d.tel,"+48-700-123456");
  f.put(&d);
  printf("ilosc elementow : %ld\n",f.getsize());
  printf("pozycja : %ld\n",f.getpos());
  strcpy(d.imi,"czerwony");
  strcpy(d.naz,"kapturek");
  strcpy(d.tel,"brak");
  f.put(&d);
  f.flush();
  printf("pozycja : %ld\n",f.getpos());
  f.close();
  f.open("c:\\adr.dat",*((ulong*)id));
  printf("ilosc elementow : %ld\n",f.getsize());
  printf("pozycja : %ld\n",f.getpos());
  f.get(&d);
  printf("%s\n%s\n%s\n",d.imi,d.naz,d.tel);
  f.del(1,0,SEEK_SET);
  printf("ilosc elementow : %ld\n",f.getsize());
  printf("pozycja : %ld\n",f.getpos());
  f.setpos(0);
  f.get(&d);
  printf("%s\n%s\n%s\n",d.imi,d.naz,d.tel);
  return 0;
}
0

Wielkie dzięki. To naprawde bardzo mi pomogło.

1 użytkowników online, w tym zalogowanych: 0, gości: 1