zapis/odczyt struktury - proszę o pomoc

0
//---------------------------------------------------------------------------

#include <vcl.h>
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
//---------------------------------------------------------------------------
/* enum nosnik_danych{
 CD ;
 DVD;
 Blu-Ray;
 }  */

 //----------------------------------------------------------------------------
void menu(){
system("cls");
cout<<"1.Dopisanie rekordu do bazy"<<endl
<<"2.Usuniecie z bazy 1 rekordu"<<endl
<<"3.Przegladanie:"<<endl
<<"4.Edycja wybranego rekordu"<<endl
<<"5.Wyzerowanie calej bazy"<< endl
<<"0.Wylacz program"<<endl;
}

void menu2(){

cout<<"1.Nastepny rekord"<<endl
<< "2.Poprzedni rekord";

}
//-----------------------------------------------------------------------------

 struct plyta{
 string wykonawca;
 string tytul;
 string nosnik;
 string format;
};
  plyta p;

void zapis_plik( plyta *dane)
{
FILE *ptr;
int rozmiar = sizeof(dane);
system("cls");
cout<<"Zapis struktury do pliku";

if ((ptr = fopen("D:\\dane.dat","ab")) == NULL)
{
cout<<"Blad otwarcia pliku";
exit(1);
}

if (fwrite(dane,rozmiar,1,ptr) !=1)
{
cout<<"Blad zapisu";
exit(2);
}

rewind(ptr);


fclose(ptr);
}
//-----------------------------------------------------------------------------
void odczyt () {

FILE *ptr;
 plyta x;
int rozmiar = sizeof(rozmiar);

if ((ptr = fopen("D:\\dane.dat","wb")) == NULL)
{
cout<<"Blad otwarcia pliku";
exit(1);
}


fread(&x,rozmiar,1,ptr);

cout<<endl<<x.wykonawca<<" "<<x.tytul<<" "<<x.nosnik<<" "<<x.format;
fclose(ptr);

}

//----------------------------------------------------------------------------



int main()
{
 int a=1;
 string tytul;
 string wykonawca;
 string nosnik;
 string format;


menu();
while(a!=0){
cin>>a;
switch(a){
case 1:{
cout<<"Wykonawca:"  ;
cin>>wykonawca;
cout<<endl<<"Tytul:";
cin>>tytul;
cout<<endl<<"Nosnik:";
cin>>nosnik;
cout<<endl<<"Format:";
cin>>format;
cout<<endl;

p.wykonawca = wykonawca;
p.tytul  = tytul;
p.nosnik = nosnik;
p.format = format;

 zapis_plik(&p);

} break;
case 2:
odczyt();
break;
}



getch();
}

getch();
        return 0;
}
//---------------------------------------------------------------------------

Mam taki problem, jak mu daje odczyt to wyświetla pusty wiersz, co tu jest źle ?

1

Musisz zapisywać składową po składowej o ile mają one typ string.

Jeżeli chcesz zapisywać tak jak to robisz teraz, to składowe muszą być tablicami char, no i rozmiar musi być rozmiarem struktury a nie tak jak u ciebie przy zapisie -rozmiar wskaźnika a przy odczycie - rozmiar samej zmiennej rozmiar.

Nie rozumiem po kiego korzystasz z fopen zamiast z fstream, przecież i tak string używasz.

1

Uzupełniając wypowiedź Dragona: do zapisu podajesz sizeof(dane). Czym jest "dane", ano wskaźnikiem. Jaki ma rozmiar? 4 lub 8 bajtów w zależności od systemu. Jakoś nie odzwierciedla rozmiaru Twoich danych. Dalej przekazujesz do zapisu znów wskaźnik - jego wartość, a nie wartość tego na co wskazuje. Przy odczycie ustalasz rozmiar na podstawie wielkości rozmiaru. Bez sensu.

0

Dzięki za pomoc, teraz może mi ktoś powiedzieć jak zmodyfikować/napisać funkcje usun_rec() ??
Chciałbym by gdy się wybiera rekord do usunięcia przenosił rekordy za nim, nadpisując go i włącznie z nadpisaniem ostatniego rekordu niczym, tak żeby móc dodać na jego miejsce nowy rekord.

 //---------------------------------------------------------------------------

#include <vcl.h>
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<fstream>
//---------------------------------------------------------------------------
/* enum nosnik_danych{
 CD ;
 DVD;
 Blu-Ray;
 }  */

//----------------------------------------------------------------------------
void menu()
{
    system("cls");
    cout<<"1.Dopisanie rekordu do bazy"<<endl
        <<"2.Usuniecie z bazy 1 rekordu"<<endl
        <<"3.Przegladanie:"<<endl
        <<"4.Edycja wybranego rekordu"<<endl
        <<"5.Wyzerowanie calej bazy"<< endl
        <<"0.Wylacz program"<<endl;
}

void menu2()
{
    cout<<endl<<"1.Nastepny rekord"<<endl
        << "2.Poprzedni rekord"<<endl<<"3.koniec"<<endl;
}

void menu3()
{
    cout<<"Jakie dane chcialbys zmienic:"<<endl
        <<"1.Wykonawca"<<endl
        <<"2.Tytyl"<<endl
        <<"3.Nosnik"<<endl
        <<"4.Format"<<endl
        <<"0.Wroc do menu glownego"<<endl;
}
//-----------------------------------------------------------------------------

struct plyta
{
    char wykonawca[20];
    char tytul[20];
    char nosnik[20];
    char format[20];
};
plyta p;

FILE *ptr;

//-----------------------------------------------------------------------------
void zapis_plik( plyta *dane)
{
    int rozmiar = sizeof(plyta);
    system("cls");
    cout<<"Zapis struktury do pliku";

    fseek(ptr,0,2) ;

    if (fwrite(dane,rozmiar,1,ptr) !=1)
    {
        cout<<"Blad zapisu";
        exit(2);
    }

}
//-----------------------------------------------------------------------------

int z=0;
void odczyt (int i)
{

    plyta x;
    int rozmiar = sizeof(plyta);

    if(i==1)
    {
        z+=rozmiar;
        fseek(ptr,z,0);
    }
    if(i==2)
    {
        z-=rozmiar;
        fseek(ptr,z,0);
    }
    if(i==0)
    {
        fseek(ptr,0,0);
    }


    fread(&x,rozmiar,1,ptr);
    cout<<endl<<x.wykonawca<<" "<<x.tytul<<" "<<x.nosnik<<" "<<x.format;

}
//----------------------------------------------------------------------------
int n=0;
void zmien(int o, char z[], int a)
{
    int rozmiar = sizeof(plyta);
    plyta c;
    n=rozmiar*o;
    fseek(ptr,n,0);
    fread(&p,rozmiar,1,ptr);

    strcpy(c.wykonawca,(a==1)?z:p.wykonawca);
    strcpy(c.tytul,(a==2)?z:p.tytul);
    strcpy( c.nosnik,(a==3)?z:p.nosnik);
    strcpy( c.format,(a==4)?z:p.format );


    fseek(ptr,n,0);
    if (fwrite(&c,rozmiar,1,ptr) !=1)
    {
        cout<<"Blad zapisu";
        exit(2);
    }

}
//----------------------------------------------------------------------------
int us=0;
int up=0;
int i=1;
int j;
void usun_rec(int k)
{
    int rozmiar = sizeof(plyta);
    plyta t;
    int d;
    do
    {
        us=(rozmiar*k);
        j=rozmiar*i;
        us+=j;

        fseek(ptr,us,0);
        fread(&p,rozmiar,1,ptr);


        strcpy(t.wykonawca,p.wykonawca);
        strcpy(t.tytul,p.tytul);
        strcpy( t.nosnik,p.nosnik);
        strcpy( t.format,p.format );


        up=us-rozmiar;
        fseek(ptr,up,0);
        if (fwrite(&t,rozmiar,1,ptr) !=1)
        {
            cout<<"Blad zapisu";
            exit(2);
        }
        ++i;
    }
    while(fgetc(ptr)!=EOF);}
//-----------------------------------------------------------------------------
void wyczysc()
{

    if ((ptr = fopen("D:\\dane.dat","wb")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }



    fclose(ptr);


}
//-----------------------------------------------------------------------------
int main()
{


    if ((ptr = fopen("D:\\dane.dat","r+b")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }


    int t=0;
    int ss=0;

    int a=1;
    char tytul[20];
    char wykonawca[20];
    char nosnik[20];
    char format[20];


    menu();
    while(a!=0)
    {
        cin>>a;
        switch(a)
        {
        case 1:
        {
            system("cls");
            cout<<"Wykonawca:"  ;
            cin>>wykonawca;
            cout<<endl<<"Tytul:";
            cin>>tytul;
            cout<<endl<<"Nosnik:";
            cin>>nosnik;
            cout<<endl<<"Format:";
            cin>>format;
            cout<<endl;

            strcpy(p.wykonawca,wykonawca);
            strcpy(p.tytul,tytul);
            strcpy(p.nosnik ,nosnik);
            strcpy(p.format,format);

            zapis_plik(&p);

        }
        break;

        case 2:
        {
            int u;
            cout<<"Usun rekord numer:";
            cin>>u;
            /* strcpy(p.wykonawca,"#");
             strcpy(p.tytul,"#");
             strcpy(p.nosnik ,"#");
             strcpy(p.format,"#");  */
            usun_rec(u);

        }
        break;

        case 3:
        {
            ss=0;
            system("cls");
            odczyt(t);
            menu2() ;


            while(ss!=3)
            {

                cin>>ss;
                if(ss==1)
                {
                    odczyt(ss);
                }

                if (ss==2)
                {
                    odczyt(ss);
                }

                if (ss!=1 && ss!=2 && ss!=3 )
                {
                    cout<<"zle polecenie";
                }
                menu2() ;
            }
        }
        break;

        case 4:
        {
            system("cls");
            plyta y;
            cout<<"Wybierz rekord ktory chcesz zmodyfikowac:"  ;
            cin>>ss;
            menu3();
            int p=1 ;
            while(p!=0)
            {
                cin>>p;

                switch(p)
                {
                case 1:
                {
                    cout<<"Wykonawca:"  ;
                    cin>>wykonawca;
                    zmien(ss,wykonawca,p);
                }
                break;
                case 2:
                {
                    cout<<endl<<"Tytul:";
                    cin>>tytul;
                    zmien(ss,tytul,p);
                }
                break;
                case 3:
                {
                    cout<<endl<<"Nosnik:";
                    cin>>nosnik;
                    zmien(ss,nosnik,p);
                }
                break;
                case 4:
                {
                    cout<<endl<<"Format:";
                    cin>>format;
                    zmien(ss,format,p);
                }
                break;

                }
                menu3();
            }
        }
        break;
        case 5:
        {
            system("cls");
            fclose(ptr);
            if ((ptr = fopen("D:\\dane.dat","wb")) == NULL)
            {
                cout<<"Blad otwarcia pliku";
                exit(1);
            }
            fclose(ptr);
            // void wyczysc() ;
            cout<<"Baza wyczyszczona"<<endl;
            if ((ptr = fopen("D:\\dane.dat","r+b")) == NULL)
            {
                cout<<"Blad otwarcia pliku";
                exit(1);
            }
        }
        break;



        }


        menu();
    }
    fclose(ptr);



    return 0;
}
//---------------------------------------------------------------------------
1

O ile nie ma znaczenia kolejność rekordów w pliku można wpisać ostatni na miejsce kasowanego po czym zmniejszyć rozmiar pliku o rozmiar rekordu.
W praktyce jest pewien problem ze zmianą rozmiaru pliku ponieważ standardowe funkcje C tego nie przywidują, przynajmniej w pracy z FILE*.
Jeżeli koniecznie musisz używać to co masz dostępne dla FILE* to tworzysz nowy plik tymczasowy do którego przepisujesz rekord po rekordzie (niekoniecznie właśnie rekord po rekordzie ale generalnie o to chodzi) bez tego kasowanego, po czym usuwasz plik obecny, przemianowujesz tymczasowy na obecny.

0

Myślałem że obędzie się bez przepisywania całości, ale cóż, tak czy owak dzięki Ci :)

Pewnie to jakiś głupi błąd ale jakoś go nie widzę, co jest teraz nie tam w tej funkcji ?

 //---------------------------------------------------------------------------

#include <vcl.h>
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<fstream>
//---------------------------------------------------------------------------
/* enum nosnik_danych{
 CD ;
 DVD;
 Blu-Ray;
 }  */

//----------------------------------------------------------------------------
void menu()
{
    //system("cls");
    cout<<"1.Dopisanie rekordu do bazy"<<endl
        <<"2.Usuniecie z bazy 1 rekordu"<<endl
        <<"3.Przegladanie:"<<endl
        <<"4.Edycja wybranego rekordu"<<endl
        <<"5.Wyzerowanie calej bazy"<< endl
        <<"0.Wylacz program"<<endl;
}

void menu2()
{
    cout<<endl<<"1.Nastepny rekord"<<endl
        << "2.Poprzedni rekord"<<endl<<"3.koniec"<<endl;
}

void menu3()
{
    cout<<"Jakie dane chcialbys zmienic:"<<endl
        <<"1.Wykonawca"<<endl
        <<"2.Tytyl"<<endl
        <<"3.Nosnik"<<endl
        <<"4.Format"<<endl
        <<"0.Wroc do menu glownego"<<endl;
}
//-----------------------------------------------------------------------------

struct plyta
{
    char wykonawca[20];
    char tytul[20];
    char nosnik[20];
    char format[20];
};
plyta p;

FILE *ptr;

//-----------------------------------------------------------------------------
void zapis_plik( plyta *dane)
{
    int rozmiar = sizeof(plyta);
    system("cls");
    cout<<"Zapis struktury do pliku";

    fseek(ptr,0,2) ;

    if (fwrite(dane,rozmiar,1,ptr) !=1)
    {
        cout<<"Blad zapisu";
        exit(2);
    }

}
//-----------------------------------------------------------------------------

int z=0;
void odczyt (int i)
{

    plyta x;
    int rozmiar = sizeof(plyta);

    if(i==1)
    {
        z+=rozmiar;
        fseek(ptr,z,0);
    }
    if(i==2)
    {
        z-=rozmiar;
        fseek(ptr,z,0);
    }
    if(i==0)
    {
        fseek(ptr,0,0);
    }


    fread(&x,rozmiar,1,ptr);
    cout<<endl<<x.wykonawca<<" "<<x.tytul<<" "<<x.nosnik<<" "<<x.format;

}
//----------------------------------------------------------------------------
int n=0;
void zmien(int o, char z[], int a)
{
    int rozmiar = sizeof(plyta);
    plyta c;
    n=rozmiar*o;
    fseek(ptr,n,0);
    fread(&p,rozmiar,1,ptr);

    strcpy(c.wykonawca,(a==1)?z:p.wykonawca);
    strcpy(c.tytul,(a==2)?z:p.tytul);
    strcpy( c.nosnik,(a==3)?z:p.nosnik);
    strcpy( c.format,(a==4)?z:p.format );


    fseek(ptr,n,0);
    if (fwrite(&c,rozmiar,1,ptr) !=1)
    {
        cout<<"Blad zapisu";
        exit(2);
    }

}
//-----------------------------------------------------------------------------
void wyczysc()
{
    system("cls");
    fclose(ptr);
    if ((ptr = fopen("D:\\dane.dat","w+b")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }
    fclose(ptr);

    cout<<"Baza wyczyszczona"<<endl;
    if ((ptr = fopen("D:\\dane.dat","r+b")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }

}
//----------------------------------------------------------------------------
int us=0;
int up=0;
int i=0;

void usun_rec(int k)
{
    FILE *tmp;
    int rozmiar = sizeof(plyta);

    if ((tmp = fopen("D:\\tmpik.dat","wb")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }
    plyta t;
    int c;

    while((c=fgetc( ptr ))  != EOF)
    {

        fseek(ptr,us,0);

        fread(&p,rozmiar,1,ptr);


        strcpy(t.wykonawca,p.wykonawca);
        strcpy(t.tytul,p.tytul);
        strcpy( t.nosnik,p.nosnik);
        strcpy( t.format,p.format );



        fseek(tmp,up,0);
        if (fwrite(&t,rozmiar,1,tmp) !=1)
        {
            cout<<"Blad zapisu";
            exit(2);
        }
        if(us==k)
        {
            us+=(rozmiar*2);
        }
        else
        {
            us+=rozmiar;
        }
        up+=rozmiar;
    }



    wyczysc();


    while((c=fgetc( tmp ) ) != EOF)
    {

        fseek(tmp,i,0);

        fread(&p,rozmiar,1,tmp);


        strcpy(t.wykonawca,p.wykonawca);
        strcpy(t.tytul,p.tytul);
        strcpy( t.nosnik,p.nosnik);
        strcpy( t.format,p.format );




        fseek(ptr,i,0);
        if (fwrite(&t,rozmiar,1,ptr) !=1)
        {
            cout<<"Blad zapisu";
            exit(2);
        }

        i+=rozmiar;
    }
    fclose(tmp);

}

//-----------------------------------------------------------------------------
int main()
{


    if ((ptr = fopen("D:\\dane.dat","r+b")) == NULL)
    {
        cout<<"Blad otwarcia pliku";
        exit(1);
    }


    int t=0;
    int ss=0;

    int a=1;
    char tytul[20];
    char wykonawca[20];
    char nosnik[20];
    char format[20];


    menu();
    while(a!=0)
    {
        cin>>a;
        switch(a)
        {
        case 1:
        {
            system("cls");
            cout<<"Wykonawca:"  ;
            cin>>wykonawca;
            cout<<endl<<"Tytul:";
            cin>>tytul;
            cout<<endl<<"Nosnik:";
            cin>>nosnik;
            cout<<endl<<"Format:";
            cin>>format;
            cout<<endl;

            strcpy(p.wykonawca,wykonawca);
            strcpy(p.tytul,tytul);
            strcpy(p.nosnik ,nosnik);
            strcpy(p.format,format);

            zapis_plik(&p);

        }
        break;

        case 2:
        {
            int u;
            cout<<"Usun rekord numer:";
            cin>>u;
            /* strcpy(p.wykonawca,"#");
             strcpy(p.tytul,"#");
             strcpy(p.nosnik ,"#");
             strcpy(p.format,"#");  */
            usun_rec(u);

        }
        break;

        case 3:
        {
            ss=0;
            system("cls");
            odczyt(t);
            menu2() ;


            while(ss!=3)
            {

                cin>>ss;
                if(ss==1)
                {
                    odczyt(ss);
                }

                if (ss==2)
                {
                    odczyt(ss);
                }

                if (ss!=1 && ss!=2 && ss!=3 )
                {
                    cout<<"zle polecenie";
                }
                menu2() ;
            }
        }
        break;

        case 4:
        {
            system("cls");
            plyta y;
            cout<<"Wybierz rekord ktory chcesz zmodyfikowac:"  ;
            cin>>ss;
            menu3();
            int p=1 ;
            while(p!=0)
            {
                cin>>p;

                switch(p)
                {
                case 1:
                {
                    cout<<"Wykonawca:"  ;
                    cin>>wykonawca;
                    zmien(ss,wykonawca,p);
                }
                break;
                case 2:
                {
                    cout<<endl<<"Tytul:";
                    cin>>tytul;
                    zmien(ss,tytul,p);
                }
                break;
                case 3:
                {
                    cout<<endl<<"Nosnik:";
                    cin>>nosnik;
                    zmien(ss,nosnik,p);
                }
                break;
                case 4:
                {
                    cout<<endl<<"Format:";
                    cin>>format;
                    zmien(ss,format,p);
                }
                break;

                }
                menu3();
            }
        }
        break;
        case 5:
        {
            wyczysc();

        }
        break;



        }


        menu();
    }
    fclose(ptr);



    return 0;
}
//---------------------------------------------------------------------------



0

Wszystko. Algorytm:

  1. Określasz rozmiar pliku fseek na koniec N = ftell/sizeof()
  2. W pętle dla każdego rekordu:
  3. wczytujesz ze starego
  4. jeżeli numer nie jest numerem kasowanego zapisujesz do nowego
  5. koniec pętli
  6. kasowanie starego
  7. przemianowanie nowego

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