Skocz do zawartości

pliki binarne


gmysu

Rekomendowane odpowiedzi

Mam sobie taki kod w C++:

 

GML
#include <iostream>

#include <fstream>

#include <string>

 

using namespace std;

 

struct book

{

string strTytul;

string strAutor;

int intRok;

};

 

book* create_table(int rozmiar)

{

book tablica [rozmiar];

fstream plik;

plik.open("baza.dat",ios::binary|ios::in);

plik.seekp(ios_base::beg);

plik.read(reinterpret_cast<char*>(&tablica),sizeof(*tablica));

plik.close();

return tablica;

}

 

int save_table(book* table)

{

fstream plik;

plik.open("baza.dat",ios::out|ios::binary);

plik.write(reinterpret_cast<char*>(table),sizeof(*table));

plik.close();

return 0;

}

 

int main()

{

int opcja = 0;

int rozmiar_tablicy = 1500;

book* tablica;

tablica = create_table(rozmiar_tablicy);

 

while(opcja!=3)

{

cout << "Wybierz akcje:" << endl;

cout << "1 - Dodaj wpis" << endl;

cout << "2 - Czytaj 0" << endl;

cout << "3 - Exit" << endl;

cin >> opcja;

 

switch(opcja)

{

case 1:

{

tablica ->strTytul = "Suicide for dummies";

tablica ->strAutor = "Ktostam";

tablica ->intRok = 2532;

cout << "Dodano ksiazke!" << endl;

}

break;

 

case 2:

{

int poz = 0;

cout << "Podaj numer pozycji do wyswietlenia: ";

cin >> poz;

cout << (tablica + poz)->strTytul << endl;

}

break;

};

}

 

save_table(tablica);

return 0;

}

 

Kompilator nie wypluwa żadnych błędów, a mimo to całość wykrzacza się po uruchomieniu. Problem leży prawdopodobnie w odczycie, bo zanim plik zostanie utworzony po raz pierwszy (i nie ma jeszcze niczego do odczytu) wszystko przynajmniej w teorii działa.

 

Pomocy!

Odnośnik do komentarza
Udostępnij na innych stronach

pokaż log debugu IDE, oraz sprawdź w calstacku na czym wywala dokładnie i pokaż nam to

Odnośnik do komentarza
Udostępnij na innych stronach

wykrzacza się po uruchomieniu

wykrzaczając się, zatrzymuje się w danym miejscu w programie, to miejsce pokazuje callstack. jak pokazuje się komunikat access violation, lub cokolwiek z przyciskami "contnue" i "break", to klikasz jdno, albo drugie i po tym masz w callstacku na samym początku pokazane, w jakiej funkcji się wysypało, ponadto w kodzie zaznacza strzałką linię, gdzie został przerwany program i nastąpiło wykrzaczenie (mowa o visual c++, jak masz inne ide to powinno być podobnie, byle nie devcpp, bo jak używasz devcpp, to nie pomogę - to jest IDE odpowiednie do śmietnika).

Odnośnik do komentarza
Udostępnij na innych stronach

Może źle się wyraziłem. Program kompiluje się i uruchamia bez problemów. Dopiero po udanym uruchomieniu pojawia się znajome wszystkim okno "program zakończył pracę blablabla". Jak już mówiłem, debugger i callstack są puste.

 

@Edit: IDE - code::blocks

Odnośnik do komentarza
Udostępnij na innych stronach

Po wrzuceniu tego kodu kompilator wywala mi to PsychiX:

 

1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Build started 2011-09-02 18:51:04.
1>PrepareForBuild:
1>  Creating directory "D:\Projekty\Programy\Game\test\Debug\".
1>InitializeBuildStatus:
1>  Creating "Debug\test.unsuccessfulbuild" because "AlwaysCreate" was specified.
1>ClCompile:
1>  main.cpp
1>d:\projekty\programy\game\test\test\main.cpp(16): error C2057: expected constant expression
1>d:\projekty\programy\game\test\test\main.cpp(16): error C2466: cannot allocate an array of constant size 0
1>d:\projekty\programy\game\test\test\main.cpp(16): error C2133: 'tablica' : unknown size
1>d:\projekty\programy\game\test\test\main.cpp(22): warning C4172: returning address of local variable or temporary
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:04.14
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Odnośnik do komentarza
Udostępnij na innych stronach

ediepl podal wlasciwe rozwiazanie. nie mozna alokowac tablicy statycznej ze zmienna jako jej rozmiaru. tak tylko mozna poprzez dynamiczna alokacje

Odnośnik do komentarza
Udostępnij na innych stronach

ediepl podal wlasciwe rozwiazanie. nie mozna alokowac tablicy statycznej ze zmienna jako jej rozmiaru. tak tylko mozna poprzez dynamiczna alokacje

 

Problem pozostaje ten sam, z tym że teraz nie działa sam zapis. Czy zamiast grzebać w tym srednio udanym tworze, ktoś mógłby napisac program który zapisuje do tablice struktur do pliku binarnego a nastepnie odczytuje je? Bede wdzieczny.

 

GML
#include <iostream>

#include <fstream>

#include <string>

 

using namespace std;

 

struct book

{

string strTytul;

string strAutor;

int intRok;

};

 

book* create_table(int rozmiar)

{

 

book* tablica;

tablica = new book [rozmiar];

 

fstream plik;

plik.open("baza.dat",ios::binary|ios::in);

plik.seekp(ios_base::beg);

plik.read(reinterpret_cast<char*>(tablica),sizeof(*tablica));

plik.close();

return tablica;

}

 

int save_table(book* table)

{

fstream plik;

plik.open("baza.dat",ios::out|ios::binary);

plik.write(reinterpret_cast<char*>(table),sizeof(book)*1500);

plik.close();

return 0;

}

 

int main()

{

int opcja = 0;

int rozmiar_tablicy = 1500;

book* tablica;

tablica = create_table(rozmiar_tablicy);

 

while(opcja!=3)

{

cout << "Wybierz akcje:" << endl;

cout << "1 - Dodaj wpis" << endl;

cout << "2 - Czytaj 0" << endl;

cout << "3 - Exit" << endl;

cin >> opcja;

 

switch(opcja)

{

case 1:

{

tablica ->strTytul = "Suicide for dummies";

tablica ->strAutor = "Ktostam";

tablica ->intRok = 2532;

cout << "Dodano ksiazke!" << endl;

}

break;

 

case 2:

{

int poz = 0;

cout << "Podaj numer pozycji do wyswietlenia: ";

cin >> poz;

cout << (tablica + poz)->strTytul << endl;

}

break;

};

}

 

save_table(tablica);

delete[] tablica;

return 0;

}

 

Powyzszy kod to to co mam teraz. Jesli okaze sie ze cudze rozwiazanie tez nie bedzie dzialac, zmieniam srodowisko. Szkoda, bo liczylem na to ze nie bede zmuszony korzystac z visual c++.

Odnośnik do komentarza
Udostępnij na innych stronach

Pomyśl, jak możesz tak zapisywać strukturę, która ma taką budowę? To nie jest POD więc nie ma prawa działać.

 

Użyj takiej:

struct Book
{
char tytul[256];
char autor[256];
int rok;
};

 

edit: oczywiście kod ma więcej błędów, przede wszystkim trzeba sprawdzać co zwraca nam dana funkcja.

Np: plik.read(reinterpret_cast<char*>(tablica),sizeof(*tablica)); Zapewniam Cię, że to nie będzie działać tak jak tego oczekujesz(o ile dobrze zrozumiałem co chcesz tu zrobić).

Odnośnik do komentarza
Udostępnij na innych stronach

Pomyśl, jak możesz tak zapisywać strukturę, która ma taką budowę? To nie jest POD więc nie ma prawa działać.

 

Użyj takiej:

struct Book
{
char tytul[256];
char autor[256];
int rok;
};

 

edit: oczywiście kod ma więcej błędów, przede wszystkim trzeba sprawdzać co zwraca nam dana funkcja.

Np: plik.read(reinterpret_cast<char*>(tablica),sizeof(*tablica)); Zapewniam Cię, że to nie będzie działać tak jak tego oczekujesz(o ile dobrze zrozumiałem co chcesz tu zrobić).

 

Po modyfikacji struktury coś się wreszcie ruszyło, tj. nie wyskakuje już access violation. Nie mialem pojecia ze string to typ ktorego nie da sie wykorzystac w ten sposob:(. Mam 1500 elementow w tablicy, a plik wynikowy (baza.dat ) nadal ma poniżej 1kb.

 

Jak powinno wyglądać poprawne rzutowanie w tym wypadku? Dzięki!

 

Edit: wygląda na to że działa. Dzięki raz jeszcze.

Odnośnik do komentarza
Udostępnij na innych stronach

Przede wszystkim sprawdzaj ile danych się wczytało i ile zapisało.

 

np: plik.read(reinterpret_cast<char*>(tablica),sizeof(*tablica)); -> sizeof(*tablica) wczyta tylko jeden element.

 

 

Tutaj jeszcze jakieś cuda wyczyniasz:

  tablica ->strTytul = "Suicide for dummies";
      tablica ->strAutor = "Ktostam";
      tablica ->intRok = 2532;

 

Masz wskaźnik na tablice, nie na pojedynczy obiekt.

 

 

 

Przykład poprawnego zapisu/wczytania:

 

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct book
{
char strTytul[256];
char strAutor[256];
int intRok;
};




int main()
{

    book* arr=new book[1500];

    fstream plik("data.txt",ios::binary|ios::out);

    
    arr[5].intRok=3456;
    arr[7].intRok=345;
    arr[1234].intRok=12;

    plik.write((char*)&arr[0],1500*sizeof(book));

    plik.close();
    plik.open("data.txt",ios::binary|ios::in);


    book* arr2=new book[1500];

    plik.read((char*)&arr2[0],1500*sizeof(book));


    cout<<"5: "<<arr2[5].intRok<<"\n";
    
    cout<<"7: "<<arr2[7].intRok<<"\n";
    
    cout<<"1234: "<<arr2[1234].intRok<<"\n";

    delete []arr;
    delete [] arr2;
    int k=0;
    cin>>k;

}

 

Zmienione dane po wczytaniu są tam gdzie powinny czyli działa, rozpisać już możesz sobie sam.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...