CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Zapis struktury z dynmicznymi tablicami

Zapis struktury z dynmicznymi tablicami

dział ogólny

Zapis struktury z dynmicznymi tablicami

Nowy postprzez oneiro » poniedziałek, 22 października 2012, 20:52

Witam,

Mam taką strukturę

KOD cpp:     UKRYJ  
struct SParametry
{
double  x_min_real,
        x_max_real,
        y_min_real,
        y_max_real;

double **tab_dyn;
unsigned dlugosc_tablicy_dyn;
};
SParametry Param;
 


i chcę zapisać taką strukturę, o ile z danymi statyczymi będzie łatwo, o tyle z tablicą 2D dynamiczną może być ciężej - jak

a) zapisać całą strukturę
b) odczytać ją później i wrzucić całość do struktury
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez Cyfrowy Baron » poniedziałek, 22 października 2012, 21:08

Nie da się tego zrobić ze strukturą, czyli nie zapiszesz tak struktury. Możesz ewentualnie użyć innej formy zapisu, czyli przepisujesz do czegoś strukturę, np. do jakiejś listy, zapisujesz listę - wczytujesz plik do listy i przepisujesz listę do struktury.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez oneiro » poniedziałek, 22 października 2012, 21:39

to inaczej - dane statyczne są w strukturze, a tablica dynamiczną jest niezależną zmienną - da się wówczas ?

PS. Czyli chodzi Ci np. o zapisanie to Memo, wywołać funkcję zapisz z memo i potem odtworzyć memo i z memo do tablicy, tak?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez Cyfrowy Baron » poniedziałek, 22 października 2012, 21:44

Jeżeli chcesz zapisać strukturę, to musisz użyć np. typu CHAR gdzie rozmiar elementów tablicy będzie z góry określony, czyli np. tak:

KOD cpp:     UKRYJ  
char[10]  x_min_real;
char[10] x_max_real;
char[10] y_min_real;
char[10] y_max_real;
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez oneiro » poniedziałek, 22 października 2012, 21:58

Chyba rozumiem, ale jeśli typ double ma 8 bajtów (8*8=64 bity) to mogę założyć, że każdy element tablicy ma 64 bity czyli char[64]. Z double nie ma problemu, z unsigned podobnie - prze konwertuję to double i zapiszę, z bool'em podobnie, albo samo 0-ra, ale 1-dynki, ze stringiem to już w ogóle łatwizna.

Ale jak z dynamiczną tablicą?

Podsumowując - każdy element mojej oryginalnej struktury przepiszę do tablicy np. CHAR o stałej długości - to są dane statyczne. A co z dynamiczną tablicą?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez Cyfrowy Baron » poniedziałek, 22 października 2012, 22:51

Nie zapiszesz struktury jeśli długość łańcucha znaków nie będzie jawnie określona. Nie zapiszesz struktury z dynamicznymi zmiennymi. Właściwie to zapiszesz, ale nie odczytasz, gdyż program nie będzie wiedział gdzie się kończy jedna zmienna a zaczyna druga.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez MisticFrezer » poniedziałek, 22 października 2012, 23:34

Należy napisać funkcję, która zapisze (do pliku, jak rozumiem) i drugą, która odczyta strukturę.
Ogólny schemat:

ZAPIS:
-Zapisz stałe dane struktury
-Zapisz wymiary dynamicznyej tablicy/tablic
-Pętelką zapisz dane tablicy

ODCZYT (do nowoutworzonej struktury)
-Odczytaj stałe dane
-Odczytaj wymiary tablicy
-Utwórz odpowiednio dużą tablicę
-Wczytaj żądana ilość danych

Cała filozofia.
Z całymi strukturami postępujemy podobnie. Należy zapisać liczbę zapisywanych struktur i odpowiednio tyle razy uruchamiać funkcję zapisu/odczytu.
Avatar użytkownika
MisticFrezer
Bladawiec
Bladawiec
 
Posty: 23
Dołączył(a): wtorek, 23 lutego 2010, 23:57
Lokalizacja: Wrocław
Podziękował : 1
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP3, Windows 7 Pro
Kompilator: BCB6, RAD Studio 2010, VS 2010
Gadu Gadu: 0
    Windows 7Opera

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez oneiro » wtorek, 23 października 2012, 07:21

Właśnie o czymś takim myślałem @Mistic, stąd w mojej strukturze dla tablicy 2D mam jej wymiar "unsigned dlugosc_tablicy_dyn" (2-gi wymiar wymiar tablicy 2D jest stały i wynosi zawsze 5) - tylko jak to zrealizować - dopiero zaczynam z obsługą plików.

Wydaje się, że wystarczy fstream , ale funkcję open z parametrem ios::out czy ios::binary (czy w ogóle jest jakaś różnica?)

Jeszcze jeśli mogę prosić jak w przypadku struktury wykorzystać poniższą funkcję:

KOD cpp:     UKRYJ  
ostream & write( const char * bufor, streamsize ilosc_danych_do_zapisu );
 


Chodzi mi o to, że bufor jest typu znakowego (tj. wskaźnik na nią), a jak chcę zapisać blok danych - za każdym razem mam rzutować dane na typ char - wszędzie jest opis jak zapisać wiersz tekstu, a jak blok danych ze struktury ze statycznymi danymi to już nie wiem.
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows 7Firefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez polymorphism » wtorek, 23 października 2012, 11:01

Wydaje się, że wystarczy fstream , ale funkcję open z parametrem ios::out czy ios::binary (czy w ogóle jest jakaś różnica?)

Jeśli tylko zapisujesz, użyj strumienia ofstream. Jeśli zapisujesz dane binarne, zawsze ustawiaj flagę ios::binary.

Co do głównego problemu, zapoznaj się z pojęciem serializacji klas oraz jej implementacją w C++ (języki wyższego poziomu wspierają serializację, C++ nie).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez oneiro » wtorek, 23 października 2012, 23:07

Fajny pomysł z tą serializacją, szkoda, że natywnie nie ma tego C/C++ w sobie, ale chyba wybiorę drogę @Mistica'a, czas zmarnowany na szukanie i próbę implementacji obcego kodu w moim wolę poświęcić na próby i samemu coś stworzyć
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez polymorphism » środa, 24 października 2012, 01:26

Sposób MisticFrezera to de facto realizacja serializacji w C++. Tyle tylko, że te funkcje, o których pisał, powinny być metodami struktury/klasy i przyjmować w parametrze referencję na strumień.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z danmicznymi tablicami

Nowy postprzez oneiro » niedziela, 28 października 2012, 00:02

Udało mi się zapisać i odtworzyć strukturę, zawierającą dwie tablice dynamiczne, ale pojawił się nowy błąd - spójrzcie proszę na mój kod
KOD cpp:     UKRYJ  
//Unit1.h
double //do wyliczenia
        OmegaB, //Omega B
        t_grubosc, //grubosc t
        //Iz, //moment bezwladnosci wzgledem osi z
        zc_zb, //Obleglosci zc-zb
        IOmegaC, //Wynikowy moment
        z0, //srodek ciezkosci
        //e0, //odleglosc od srodka do przeciecia osi
        //Is, //moment statyczny
        //Iyc, //Glowny centralny Moment bezwladnosci Iy
        dlugosc_luku, //dlugosc luku
                a,
                b,
                b1,
                b0,
                ca,
                m,
                beta,
                krok,
                Apole, //Pole powiechni
                k, //=pi*ca/b0;
                l_cypek, //dlgosc cypka
                granica_gorna,
                granica_dolna,
                p1,p2,p3, //punkty calkowania
                beta_dolny_zakres, //Beta min - do dlugosci elemntrego odcina
                beta_gorny_zakres, //Beta max - do dlugosci elemntrego odcina
                beta_min, //potrzebne, do obliczenie artykulu na PP
                //beta_max=beta;//potrzebne, do obliczenie artykulu na PP
        CalkaFun,h0,iloraz,ilosc_iteracji_ekstrapolacji,
        PI_przez_Beta,PI_przez_Beta_kwadrat,
                 x_min_real,
                x_max_real,
                y_min_real,
                y_max_real;

bool   czy_zmiana_danych, //potrzebe do decyzji, czy rysowac czy nie
        czy_obliczone, //potrzbne, do decyzji czy rysowac punkty charakterystyczne
        mozna_kopiowac_do_cufsm,
        czy_jest_rysunek,
        czy_pierwszy_raz;
String sep[2];
char  point;
unsigned  ilosc_puktow_pi_2_do_beta,
          dlugosc_tablicy_ele,
          dlugosc_tablicy_nod;
double tab_mat[6];
double **tab_nod; //do teblicy dynamicznej przechwoujacej wspolrzedne
double **tab_ele;
};
extern SParametry Param;
 


Dwa kody - zapisu i odczytu
KOD cpp:     UKRYJ  
//zapis
ofstream plik;
plik.open("plik.txt",ios::binary);
if( plik.good() == true )
 {
 plik.write(reinterpret_cast<char*>(&Param),sizeof(Param));
 for (int i=0; i<Param.dlugosc_tablicy_ele; i++)
  for (int j=0; j<3; j++)
  {
  plik.write(reinterpret_cast<char*>(&Param.tab_ele[i][j]),sizeof(double));
  }
 for (int i=0; i<Param.dlugosc_tablicy_nod; i++)
  for (int j=0; j<5; j++)
  {
  plik.write(reinterpret_cast<char*>(&Param.tab_nod[i][j]),sizeof(double));
  }
 } //good open file
plik.close();
 


oraz odczyt

KOD cpp:     UKRYJ  
//odczyt
ifstream plik2;
plik2.open("plik.txt",ios::binary);
if( plik2.good() == true )
 {

  //jesli są tablice, kasujemy je
 //nody
 if (Param.tab_nod!=NULL)
  {
  for (unsigned j = 0; j <(Param.dlugosc_tablicy_nod); j++)
   delete[] Param.tab_nod[j];
  // zwalniamy tablicę wskaźników do nich
  delete[] Param.tab_nod;
  Param.tab_nod = NULL;
  };

 //elemnty
 if (Param.tab_ele!=NULL)
  {
  for (unsigned j = 0; j <(Param.dlugosc_tablicy_ele); j++)
   delete[] Param.tab_ele[j];
  // zwalniamy tablicę wskaźników do nich
  delete[] Param.tab_ele;
  Param.tab_ele = NULL;
  };

 //odczytuję częsc statyczna zbiorow
   plik2.read(reinterpret_cast<char*>(&Param),sizeof(Param));
   unsigned end_static=plik2.tellg();

 //tworze dynamiczna tablice, do zapisania wspolrzednych
 //double *tab_nod; jest w glownej definicji
 //double **tab_nod; // Tabela ze wspolrzednymi punktow - wskaźnik do niej ("drugiego stopnia"!)
 //najpierw tworzymy tablicę wskaźników do kolejnych wierszy

 //nody
 Param.tab_nod = new double* [Param.dlugosc_tablicy_nod];
 for (unsigned j = 0; j<(Param.dlugosc_tablicy_nod); j++)
     {     // nastepnie alokujemy te wiersze
     Param.tab_nod[j] = new double [3];
     }
 //elementy
 Param.tab_ele = new double* [Param.dlugosc_tablicy_ele];
 for (unsigned j = 0; j<(Param.dlugosc_tablicy_ele); j++)
     {     // nastepnie alokujemy te wiersze
     Param.tab_ele[j] = new double [5];
     }

 //odczytujemy dane
 plik2.seekg(end_static+1,ios::beg);
 for (int i=0; i<Param.dlugosc_tablicy_ele; i++)
   for (int j=0; j<3; j++)
  {
  plik2.read(reinterpret_cast<char*>(&Param.tab_ele[i][j]),sizeof(double));
  }
 for (int i=0; i<Param.dlugosc_tablicy_nod; i++)
   for (int j=0; j<5; j++)
  {
  plik2.read(reinterpret_cast<char*>(&Param.tab_nod[i][j]),sizeof(double));
  }


plik2.close();

//Uzupelniamy dane
Memo1->Clear();
Memo2->Clear();
Form2->listuj_nod();
Form2->listuj_ele();


Edit1->Text=Param.a;
Edit6->Text=Param.t_grubosc;
Edit2->Text=Param.b;
Edit4->Text=Param.ca;
Edit3->Text=Param.b1;
Edit5->Text=Param.m;
Edit16->Text=Param.Apole;
Edit25->Text=Param.b0;

//zmianily sie dane!
Param.czy_zmiana_danych=True;

 




I gdzie mam błąd - po odczytaniu danych dane są OK, ale ciężko powiedzieć co się dzieje dalej. Otóż po odczytaniu danych jeśli chcę jeszcze raz otrzymać wyniki (czyli obliczyć jakieś wartości i zapisać do tab. dyn - ale przedtem muszę usunąć stare tablice dyn) wywala mi access violation, niekiedy usuwa mi dobrze i zakłada kolejne tablice dobrze, ale nie mogę się do niech odnieść - access violation.

Moje podejrzenia się takie, że zapisując dane do pliku zapisuję adres wskaźnika (tablice dynamiczne), a po odczytaniu odtwarzam go, ale program utworzył już jakieś inne adresy - nie wiem jak to ubrać w słowa, ale coś w ten
deseń.

Być może chodzi po polecenie plik.tellg() - ostatnie dwa bajty to tablice dynamiczne, może powinien +/-2 ?
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z dynmicznymi tablicami

Nowy postprzez polymorphism » niedziela, 28 października 2012, 12:11

KOD cpp:     UKRYJ  
struct SParametry
{
    ...

    String sep[2];
    ...
};

...
plik2.read(reinterpret_cast<char*>(&Param), sizeof(Param));
 

Nie możesz odczytywać w ten sposób struktury, w której znajdują się struktury/klasy, które nie są POD-ami. Dlatego pisałem o tym, żebyś się zapoznał z serializacją i jej realizacją w C++.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z dynmicznymi tablicami

Nowy postprzez oneiro » niedziela, 28 października 2012, 14:03

Z tego co wyczytałem, sprawa dotyczy bardziej klas i (teoretycznie) wystarczy przed klasą dać [Serializabe] i jedną bibliotekę i niby po problemie, ale chyba nie tędy droga (podobnie ze strukturą, ale jakoś nie mogę nic sensownego znaleźć na ten temat).

Super programistą nie jestem (powiedziałbym, że kiepskim) i aż tak głęboko w analizę/teorię nie wnikam. Nie mniej chyba wiem w czym błąd - podczas zapisu nie ma znacznie czy jest to tablica dynamiczna, czy statyczna - muszę dla każdej tablicy zrobić pętelkę for po ilości elementów i zapisać każdy element, a potem każde odczytać w ten sam sposób - ale to po obiedzie :)

Co zmieniłem w kodzie - zamiast tablica stringów jest tablica char'ów, ale to nie zmienia nic.
Zmieniłem też miejsce, gdzie podejrzewam błąd na poniższą:
KOD cpp:     UKRYJ  
 plik2.seekg(end_static,ios::beg);
 


PS Dziś mogłem 4x odczytać i zrobić obliczenia, a z 5-tym razem to co poniżej już za każdym razem ....

Kod: Zaznacz cały
---------------------------
Debugger Exception Notification
---------------------------
Project Project2.exe raised exception class EAccessViolation with message 'Access violation at address 00421F9C in module 'Project2.exe'. Write of address 0000004C'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help   
---------------------------




//EDIT

Dodanie pętli for dużo nie pomogło....
Avatar użytkownika
oneiro
Homos antropiczny
Homos antropiczny
 
Posty: 96
Dołączył(a): niedziela, 17 czerwca 2012, 23:19
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: brak systemu
Kompilator: C++ Builder v6
Gadu Gadu: 0
    Windows XPFirefox

Re: Zapis struktury z dynmicznymi tablicami

Nowy postprzez polymorphism » niedziela, 28 października 2012, 14:24

Z tego co wyczytałem, sprawa dotyczy bardziej klas (...)

Czyli Twój przypadek. Między strukturą a klasą nie ma większej różnicy.

(...) i (teoretycznie) wystarczy przed klasą dać [Serializabe] i jedną bibliotekę i niby po problemie

To raczej nie jest C++...

Nie mniej chyba wiem w czym błąd (...)

Napisałem w czym błąd.

KOD cpp:     UKRYJ  
plik2.seekg(end_static+1,ios::beg);

A to po co?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości