tablica struktur, zapis do pliku binarnego

0

Witam,
Czy mógłby ktoś naświetlić jak zapisać i odczytać tablicę struktur do pliku binarnego?
Aktualnie zapisuje tylko jedną linijkę i to w trakcie działania programu, po zrestartowaniu nie ma czego odczytać...

struct wygrany
{
	AnsiString imie;
	AnsiString czas;
	int punkty;
	AnsiString data;
};
wygrany top10[10];

Odczyt przy starcie programu:

fstream plik1;
plik1.open( "plik.dat", std::ios::binary | std::ios::in );
if (plik1 != NULL)
	for (int i = 0; i < 10; i++)
	{
		plik1.read((char*)&top10[i].imie,sizeof(top10[i].imie));
		plik1.read((char*)&top10[i].czas,sizeof(top10[i].czas));
		plik1.read((char*)&top10[i].punkty,sizeof(top10[i].punkty));
		plik1.read((char*)&top10[i].data,sizeof(top10[i].data));
	}
plik1.close();

Zapis

int min=top10[0].punkty;
int nrmin=0;
for (int i = 9; i >=0 ; i--)
	if(min > top10[i].punkty || top10[i].punkty==NULL)
	{
		min = top10[i].punkty;
		nrmin = i;
	}
top10[nrmin].imie=Edit1->Text;
top10[nrmin].czas=Label7->Caption;
top10[nrmin].punkty=Label3->Caption.ToInt();
top10[nrmin].data=Label5->Caption;
fstream plik;
plik.open( "plik.dat", std::ios::binary | std::ios::out );
plik.write((char*)&top10[nrmin].imie,sizeof(top10[nrmin].imie));
plik.write((char*)&top10[nrmin].czas,sizeof(top10[nrmin].czas));
plik.write((char*)&top10[nrmin].punkty,sizeof(top10[nrmin].punkty));
plik.write((char*)&top10[nrmin].data,sizeof(top10[nrmin].data));

plik.close();
0

Co to jest AnsiString? Jakaś klasa z buildera?
Po zapisie plik jest pusty czy coś w nim jest?

0

AnsiString to zmienna, dłuższy string.
plik zostaje zapisany ma 4kb

1

AnsiString to nie jest zmienna! Zmienną jest imie czy czas. Ehh sam poszukałem... to jest klasa, a dokładniej konkretyzacja szablonu AnsiStringT<0>. Nie możesz tego zapisywać w ten sposób, bo napisu samego w sobie nie zapisuje tylko wskaźnik do niego i resztę zmiennych pomocniczych. To jest coś jak std::string, a nawet pewnie to opakowuje, albo dziedziczy po tym.

Kodu mi się nie chce pisać, ale powinno to wyglądać tak:
Najpierw zapisujesz długość napisu, potem sam napis i przy odczycie pobierasz najpierw długość napisu, a potem wczytujesz ten napis do jakiegoś bufora(np. char *buffer = new char[dlugosc_napisu+1] - na końcu musisz dodać znak \0. Dopiero z bufora możesz to wrzucić do zmiennej typu AnsiString(pewnie tak zadziała: imie = buffer).
Do wyciągnięcia napisu z zmiennej typu AnsiString użyj jej metody c_str(), która zwraca c-string z napisem.

Dodatkowo, jeżeli piszesz w C++ to imho lepiej używać rzutowań z c++ (static_cast, dynamic_cast, reinterpret_cast /ten Cię tu zainteresuje/). Jest z tym jeszcze jeden problem - przy takim rzutowaniu między typami wskaźników mogą pojawić się problemy jeżeli będzie włączona optymalizacja i poleci tzw. strict-aliasing.

0

Dziękuję bardzo :)
I przepraszam za małe faux pas w związku z nazwaniem AnsiString zmienną, miałem na myśli że to typ zmiennej.
Zmieniłem z ansistring na char i jest ok!

strcpy(top10[nrmin].imie, Edit1->Text.t_str());
0

Zapis jednego pola:

  ofstream plik("plik.dat",std::ios::binary);
  int Len=top10[i].imie.Length();
  plik.write((char*)&Len,sizeof(int));
  plik.write((char*)&top10[i].imie[1],Len);

Odczyt jednego pola:

  ifstream plik("plik.dat",std::ios::binary);
  int Len;
  plik.read((char*)&Len,sizeof(int));
  top10[i].imie.SetLength(Len);
  plik.read((char*)&top10[i].imie[1],Len);

Liczbowe wczytujesz i zapisujesz bezpośrednio.
Z pozostałymi polami typu napis podobnie.

Dla daty i czasu jest typ TDateTime;
Bardzo łatwo konwertuje się z napisu i do napisu.

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