• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Wczytywanie z pliku binarnego

Object Storage Arubacloud
0 głosów
441 wizyt
pytanie zadane 17 czerwca 2019 w C i C++ przez BartekSV123 Nowicjusz (240 p.)

WItam,

mam problem z wczytywaniem do listy wskaźników klasy bazowej klas pochodnych z pliku binarnego

Mój kod wygląda tak

class Baza_pojazdow
{
public:
	int size;
	deque<Pojazd*> pojazdy;
	string nazwa_pliku;

	void wczytaj()
	{
		ifstream dane(nazwa_pliku, ios::binary);

		string wybor;

		while (!dane.eof())
		{
			dane.read((char*)(&wybor), sizeof(string));

			if (wybor == "osobowy")
			{
				char* temp = new char[sizeof(Osobowy)];
				dane.read(temp, sizeof(Osobowy));
				Pojazd* nowy = (Osobowy*)temp;
				pojazdy.push_back(nowy);
			}
		}
	
		dane.close();
	}

Używam VS 2019 i w debugerze widzę że wszystkie dane dobrze się wczytały ale w momencie zakończenia się funkcji wczytaj wyskakuje mi błąd

 

Zgłoszono wyjątek: naruszenie dostępu do odczytu.
_Pnext było 0x19EB44.

w pliku xmemory0 

 for (_Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; *_Pnext != nullptr; // <-- o tu
             *_Pnext                   = (*_Pnext)->_Mynextiter) {
            (*_Pnext)->_Myproxy = nullptr;
        }

nie znalazłem nic w internecie na ten temat, z góry dziękuje za odpowiedz

 

to reszta kodu

include <iostream>
#include <fstream>
#include <deque>
#include <string>
#include <algorithm>
using namespace std;

class Pojazd
{
protected:
	string jaki;
	string marka;
	string rejestracja;
	short int rok_produkcji;
	short int moc_silnika;
	short int pojemnosc_baku;

public:
	Pojazd() {}
	Pojazd(string _jaki, string _marka, string _rejestracja,short int _rok_produkcji, short int _moc_silnika, short int _pojemnosc_baku)
		: jaki(_jaki), marka(_marka), rejestracja(_rejestracja), rok_produkcji(_rok_produkcji), moc_silnika(_moc_silnika), pojemnosc_baku(_pojemnosc_baku) {}

	virtual ~Pojazd() {}

	virtual void wyswietl() = 0;

	void podstawowe_info()
	{
		cout << "----------------------------------------\n";
		cout << "typ: " << jaki << "\n";
		cout << "marka: " << marka << "\n";
		cout << "rejestracja: " << rejestracja << "\n";
		cout << "rok produkcji: " << rok_produkcji << "\n";
		cout << "moc silnika: " << moc_silnika << " KM\n";
		cout << "pojemnosc baku: " << pojemnosc_baku << " l\n";
	}

	virtual void zapisz(ofstream &dane) = 0;
};

class Osobowy : public Pojazd
{
private:
	short int ilosc_miejsc;
	short int pojemnosc_bagaznika;

public:
	Osobowy()
	:ilosc_miejsc(0), pojemnosc_bagaznika(0) {}
	Osobowy(string _jaki, string _marka, string _rejestracja, short int _rok_produkcji, short int _moc_silnika, short int _pojemnosc_baku, short int _ilosc_miejsc, short int _pojemnosc_bagaznika)
		: Pojazd(_jaki, _marka, _rejestracja, _rok_produkcji, _moc_silnika, _pojemnosc_baku), ilosc_miejsc(_ilosc_miejsc), pojemnosc_bagaznika(_pojemnosc_bagaznika) {}

	virtual ~Osobowy () {}

	virtual void wyswietl()
	{
		podstawowe_info();
		cout << "ilosc miejsc: " << ilosc_miejsc << "\n";
		cout << "pojemność bagaznika: " << pojemnosc_bagaznika << "\n";
	}
	
	virtual void zapisz(ofstream &dane)
	{
		dane.write((char*)(&jaki), sizeof(jaki));
		dane.write((char*)(this), sizeof(Osobowy));
	}
};

class Motor : public Pojazd
{
private:
	bool czy_z_doczepka;

public:
	Motor() {}
	Motor(string _jaki, string _marka, string _rejestracja, short int _rok_produkcji, short int _moc_silnika, short int _pojemnosc_baku, bool _czy_z_doczepka)
		: Pojazd(_jaki, _marka, _rejestracja, _rok_produkcji, _moc_silnika, _pojemnosc_baku), czy_z_doczepka(_czy_z_doczepka) {}

	virtual ~Motor() {}

	virtual void wyswietl()
	{
		podstawowe_info();
		cout << "czy z doczepka: " << (czy_z_doczepka ? "TAK" : "NIE") << "\n";
	}

	virtual void zapisz(ofstream &dane)
	{
		dane.write((char*)(&jaki), sizeof(jaki));
		dane.write((char*)(this), sizeof(Osobowy));
	}
};

class Baza_pojazdow
{
public:
	int size;
	deque<Pojazd*> pojazdy;
	string nazwa_pliku;

	void wczytaj()
	{
		ifstream dane(nazwa_pliku, ios::binary);

		string wybor;

		while (!dane.eof())
		{
			dane.read((char*)(&wybor), sizeof(string));

			if (wybor == "osobowy")
			{
				char* temp = new char[sizeof(Osobowy)];
				dane.read(temp, sizeof(Osobowy));
				Pojazd* nowy = (Osobowy*)temp;
				pojazdy.push_back(nowy);
			}
		}
	
		dane.close();
	}

	Baza_pojazdow()
		: size(0), nazwa_pliku("dane.bin") 
	{}

	~Baza_pojazdow()
	{}

	void Dodaj()
	{
		system("CLS");
		cout << "Jaki pojazd chcesz dodac?\n1 - osobowy\n2  -motor\n";
		short int wybor;
		
		while (true)
		{
			try
			{
				cin >> wybor;
				if (wybor != 1 && wybor != 2)
					throw 1;
				else
					break;
			}
			catch (...)
			{
				cout << "Podales zly numer! sproboj jeszcze raz\n";
			}
		}

		if (wybor == 1)
		{
			system("CLS");
			cout << "Dodawanie samochodu osobowego\n----------------------------------------\n";
			string _jaki="osobowy";
			string _marka;
			string _rejestracja;
			short int _rok_produkcji;
			short int _moc_silnika;
			short int _pojemnosc_baku;
			short int _ilosc_miejsc;
			short int _pojemnosc_bagaznika;

			cout << "Podaj marke: ";
			cin >> _marka;
			cout << "\n";

			cout << "Podaj rejestracje: ";
			cin >> _rejestracja;
			cout << "\n";

			cout << "Podaj rok produkcji: ";
			cin >> _rok_produkcji;
			cout << "\n";

			cout << "Podaj moc silnika: ";
			cin >> _moc_silnika;
			cout << "\n";

			cout << "Podaj pojemnosc baku: ";
			cin >> _pojemnosc_baku;
			cout << "\n";

			cout << "Podaj ilosc miejsc: ";
			cin >> _ilosc_miejsc;
			cout << "\n";

			cout << "Podaj pojemnosc bagaznika: ";
			cin >> _pojemnosc_bagaznika;
			cout << "\n";

			pojazdy.push_back(new Osobowy(_jaki, _marka, _rejestracja, _rok_produkcji, _moc_silnika, _pojemnosc_baku, _ilosc_miejsc, _pojemnosc_bagaznika));

		}
		size++;
	}

	void zapisz()
	{
		ofstream dane(nazwa_pliku, ios::binary);
		dane.clear();

		for_each(pojazdy.begin(), pojazdy.end(), [&](Pojazd* do_zapisu) {do_zapisu->zapisz(dane); });

		dane.close();
	}
	
	void wyswietl()
	{
		system("CLS");
		for_each(pojazdy.begin(), pojazdy.end(), [&](Pojazd* do_wyswietlenia) {do_wyswietlenia->wyswietl(); });
	}
};

int main()
{
	Baza_pojazdow baza;

	while (true)
	{
		system("CLS");
		int wybor;
		cout << " 1 - dodaj, 2 - wyswietl, 3 - zapisz, 4 - wczytaj\n";
		cin >> wybor;
		switch (wybor)
		{
		case 1:
			baza.Dodaj();
			break;
		case 2:
			baza.wyswietl();
			break;
		case 3:
			baza.zapisz();
			break;
		case 4:
			baza.wczytaj();
			break;
		}
	}
}

 

1 odpowiedź

+1 głos
odpowiedź 17 czerwca 2019 przez adrian17 Ekspert (344,860 p.)
To z natury nie ma prawa zadziałać.

Nie można tak po prostu struktury wskaźnika sobie binarnie zrzucić do pliku, bo... tam tak naprawdę nie ma samych danych. Struktura std::string-a to głównie wskaźnik na dynamicznie zaalokowaną pamięć. Wczytana z pliku sama liczbowa wartość wskaźnika nie ma żadnej wartości bez pamięci, na którą wskazywał.

Do serializowania bardziej złożonych typów, potrzebujesz jakąś bibliotekę do serializacji. Jest ich masa w różnych wariantach, tekstowe lub binarne, prostsze i wydajniejsze, parę w Booście... pewnie najprościej byłoby dumpować do JSONa. Lub ewentualnie z ręki do CSV, jeśli nie przechowujesz kontenerów. Ale nie próbuj z ręki serializować binarnie.
komentarz 17 czerwca 2019 przez BartekSV123 Nowicjusz (240 p.)
Dzięki,

A mógł byś pokazać prosty przykład jak taką serializacje zastosować?
2
komentarz 17 czerwca 2019 przez adrian17 Ekspert (344,860 p.)

Hm... przykład kompletnie na szybko, raczej dość brzydki ale by zadziałał, z biblioteką https://github.com/nlohmann/json :

#include "json.hpp"

using json_t = nlohmann::json;
 
class Pojazd
{
    virtual json_t to_json() {
        return json_t{
            {"jaki", jaki},
            {"marka", marka},
            {"rejestracja", rejestracja},
            {"rok_produkcji", rok_produkcji},
            {"moc_silnika", moc_silnika},
            {"pojemnosc_baku", pojemnosc_baku},
        };
    }
};
 
class Osobowy : public Pojazd
{
    virtual json_t to_json() override final
    {
        auto json = Pojazd::to_json();
        json["ilosc_miejsc"] = ilosc_miejsc;
        json["pojemnosc_bagaznika"] = pojemnosc_bagaznika;
        return json;
    }

    static Osobowy* from_json(const json_t &j) 
    {
        return new Osobowy(
            j["jaki"],
            j["marka"],
            j["rejestracja"],
            j["rok_produkcji"],
            j["moc_silnika"],
            j["pojemnosc_baku"],
            j["ilosc_miejsc"],
            j["pojemnosc_bagaznika"]
        );
    }
};
 
class Baza_pojazdow
{ 
    void wczytaj()
    {
        pojazdy.clear();

        ifstream dane(nazwa_pliku);
        json_t json;
        dane >> json;
        for (const auto &row : json) {
            if (row["jaki"] == "osobowy") {
                pojazdy.push_back(Osobowy::from_json(row));
            }
        }
    }

    void zapisz()
    {
        json_t json;

        for (const auto& pojazd : pojazdy) {
            json.push_back(pojazd->to_json());
        }
        ofstream dane(nazwa_pliku);
        dane << json;
    }
};

 

Podobne pytania

0 głosów
1 odpowiedź 128 wizyt
pytanie zadane 3 grudnia 2018 w C i C++ przez Moti Użytkownik (650 p.)
0 głosów
1 odpowiedź 131 wizyt
pytanie zadane 18 czerwca 2018 w C i C++ przez kietek Początkujący (280 p.)
0 głosów
1 odpowiedź 945 wizyt

92,554 zapytań

141,399 odpowiedzi

319,535 komentarzy

61,938 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...