/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
Bech_bb 500
kyllekylle 500
jdjespers.. 500
gibson 300
scootergr.. 300
molokyle 287
10  strarup 270
at skrive og læse objekter i c++ ?
Fra : acs


Dato : 13-01-10 14:46

Hejsa. Jeg har nogen erfaring med java hvor det at skrive et objekt jo
kan klares med "objectoutputstream". Nu har jeg forsøgt mig med
borland c++ hvor jeg savner en tilsvarende rutine. efter lidt søgning
på nettet er jeg kommet frem til at der tilsyneladende findes to
metoder. den ene er at skrive til et fstream objekt idet man skriver
objektet som et char array ved at give objektets pointer og objektets
størrelse som argument. det virker - tilsyneladende. MEN når jeg så
skal læse fra filen igen, så går mit program ned!
jeg mistænker fejlen for at være at det objekt jeg skaber når jeg
læser fra filen ikke har den rigtige størrelse - hvordan skulle
computeren også på forhånd vide hvor meget hukommelse der skal
allokeres til objektet inden man læser det fra filen?
den anden metode er at man i selve objektets klasse overloader << og
>> operatorerne. det involverer vist et Ofstream objekt, men de
eksempler jeg har kunnet finde synes jeg ikke at jeg kunne hitte hoved
eller hale i.
mine objekter vil ikke have en på forhånd fastlagt størrelse, da de
indeholder arrays hvis dimension bliver fastlagt på runtimetidspunktet
og computeren vil derfor skulle bestemme størrelsen af det objekt den
skal hente fra filen når den læser, forestiller jeg mig.

en testversion af rutinen der skal læse/skrive til en fil har jeg her:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "inputmanager.h"
//#include "forsvarsby.h"
void main()
{
inputbehandler inp; //objekt der håndterer indtastning af data og
returnerer et array af objekter af typen forsvarsby
forsvarsby *byer=inp.forsvarsinput(); //arrayet af objekter som jeg
ønsker at skrive til en fil
fstream s;
s.open("configtest.out",ios::in|ios::out|ios::binary|ios::app);
s.write ( (char *)(&byer) , sizeof(byer) );
cout<<"byer skrevet"<<endl;
s.close();
forsvarsby *by2; //nyt array af samme type objekt (forsvarsby) der
skal teste om data er skrevet rigtigt ned
s.open("configtest.out",ios::in);
s.read ((char *)&by2,sizeof(by2)); //jeg går ud fra at sizeof skal
have by2 som argument ???
s.close();
cout<<by2[0].navn<<by2[0].xpos<<endl<<by2[1].navn<<endl; // *se
kommentar nedenunder
};

Jeg ved at det lykkes at skrive til filen og læse fra den, da det en
enkelt gang er lykkedes mig at få output fra by2 ved kun af cout'e
variable fra by2[0].

Hvad går der galt og er der evt en bedre metode at gøre dette på?

 
 
Arne Vajhøj (13-01-2010)
Kommentar
Fra : Arne Vajhøj


Dato : 13-01-10 23:21

On 13-01-2010 16:45, acs wrote:
> Hejsa. Jeg har nogen erfaring med java hvor det at skrive et objekt jo
> kan klares med "objectoutputstream". Nu har jeg forsøgt mig med
> borland c++ hvor jeg savner en tilsvarende rutine. efter lidt søgning
> på nettet er jeg kommet frem til at der tilsyneladende findes to
> metoder. den ene er at skrive til et fstream objekt idet man skriver
> objektet som et char array ved at give objektets pointer og objektets
> størrelse som argument. det virker - tilsyneladende. MEN når jeg så
> skal læse fra filen igen, så går mit program ned!
> jeg mistænker fejlen for at være at det objekt jeg skaber når jeg
> læser fra filen ikke har den rigtige størrelse - hvordan skulle
> computeren også på forhånd vide hvor meget hukommelse der skal
> allokeres til objektet inden man læser det fra filen?
> den anden metode er at man i selve objektets klasse overloader<< og
>>> operatorerne. det involverer vist et Ofstream objekt, men de
> eksempler jeg har kunnet finde synes jeg ikke at jeg kunne hitte hoved
> eller hale i.
> mine objekter vil ikke have en på forhånd fastlagt størrelse, da de
> indeholder arrays hvis dimension bliver fastlagt på runtimetidspunktet
> og computeren vil derfor skulle bestemme størrelsen af det objekt den
> skal hente fra filen når den læser, forestiller jeg mig.
>
> en testversion af rutinen der skal læse/skrive til en fil har jeg her:
> #include<iostream>
> #include<string>
> #include<fstream>
> using namespace std;
> #include "inputmanager.h"
> //#include "forsvarsby.h"
> void main()
> {
> inputbehandler inp; //objekt der håndterer indtastning af data og
> returnerer et array af objekter af typen forsvarsby
> forsvarsby *byer=inp.forsvarsinput(); //arrayet af objekter som jeg
> ønsker at skrive til en fil
> fstream s;
> s.open("configtest.out",ios::in|ios::out|ios::binary|ios::app);
> s.write ( (char *)(&byer) , sizeof(byer) );
> cout<<"byer skrevet"<<endl;
> s.close();
> forsvarsby *by2; //nyt array af samme type objekt (forsvarsby) der
> skal teste om data er skrevet rigtigt ned
> s.open("configtest.out",ios::in);
> s.read ((char *)&by2,sizeof(by2)); //jeg går ud fra at sizeof skal
> have by2 som argument ???
> s.close();
> cout<<by2[0].navn<<by2[0].xpos<<endl<<by2[1].navn<<endl; // *se
> kommentar nedenunder
> };
>
> Jeg ved at det lykkes at skrive til filen og læse fra den, da det en
> enkelt gang er lykkedes mig at få output fra by2 ved kun af cout'e
> variable fra by2[0].
>
> Hvad går der galt og er der evt en bedre metode at gøre dette på?

Dine umiddelbare problemer skyldes nom at sizeof af en pointer
returnerer størrelsen af pointeren (typisk vil 4 eller 8) og altså
ikke størrelsen af data som pointene peger på.

Arne

Arne Vajhøj (13-01-2010)
Kommentar
Fra : Arne Vajhøj


Dato : 13-01-10 23:22

On 13-01-2010 16:45, acs wrote:
> Hejsa. Jeg har nogen erfaring med java hvor det at skrive et objekt jo
> kan klares med "objectoutputstream". Nu har jeg forsøgt mig med
> borland c++ hvor jeg savner en tilsvarende rutine.

C++ er anderledes end Java.

http://www.parashift.com/c++-faq-lite/serialization.html

forklarer lidt om mulighederne i C++.

Arne

Mogens Hansen (14-01-2010)
Kommentar
Fra : Mogens Hansen


Dato : 14-01-10 10:17

> "acs" <abbaratet@live.dk> wrote in message
> news:54f0b4d4-adbe-404a-9381-a15fcb1aeb1b@m26g2000yqb.googlegroups.com...

[8<8<<8]
> Hvad går der galt og er der evt en bedre metode at gøre dette på?

Det der helt konkret går galt er at du skriver adressen på pegeren byer ud i
filen, for derefter ved indlæsning at tildele by2 værdien af adressen på
byer.
Det giver ingen mening (så programmet crasher), og dine cast (jeg
foretrækker C++ cast frem for C cast - i dette tilfælde skal det være
reinterpret_cast) skjuler det for dig.
Castene siger til compiler "bare rolig - jeg har styr på hvad der sker" ...

Derudover giver det den konkrete værdi af en pointer ikke meget mening at
gemme i en fil. Den kan bruges en unik identifikation af et objekt, men kan
bruges som pointer værdi når den læses igen.
Ydermere skal objekts _værdi_ skrives ud i filen (f.eks. byens navn) hvis
den skal kunne genskabes.

Det du har fat i er serialisering af objekter.
Borland C++ havde i gamle dage et klassebibliotek der kunne det - jeg ved
faktisk ikke om det stadig er tilfældet (selvom jeg fortsat bruger .
Det virkede udemærket, men den slags teknologi giver nemt nogle problemer
med versionering osv. fordi det laver en hård kobling mellem
implementeringen af et objekt og persistens formatet.
Hvis det skal være mere robust syntes jeg man er bedre tjent med at bruge en
egentlig database eller skrive informationen i en tekst konfigurations fil
(f.eks. en INI fil).

Hvis man har brug for serialisering af objekter i C++ vil jeg anbefale at
kigge på Boost.Serialization
http://www.boost.org/doc/libs/1_41_0/libs/serialization/doc/index.html
Jeg har ikke selv prøvet det bibliotek, men bibliotekerne i Boost plejer at
være gode.

Java har reflection, som (så vidt jeg husker) kan give information på
run-time om hvilke data-medlemmer der er i en klasse, og dermed kan
automatisere serialisering på run-time.
C++ har ikke reflection, og hvis man skulle automatisere serialisering i C++
skal det gøres på compile-time med ekstra værktøjer, og der bliver nogle
problemer med hvor objekterne er allokeret (i Java har man kun een
mulighed - i C++ har man (mindst) 3).

Iøvrigt mener jeg generelt at man er bedst tjent med at bruge engelske navne
på egne klasser, objekter og kommentarer - men det er en helt anden sag.
Alle nøgleord i C++ (og mange andre programmeringssprog) er engelsk, og man
får en underlig sammenblanding af engelsk og dansk.
Når man har vedligeholdt programmer, der oprindeligt er skrevet i Tyskland,
Frankrig og Finland, bliver man mere overbevist om den holdning

--
Venlig hilsen

Mogens Hansen



Jacob Bunk Nielsen (14-01-2010)
Kommentar
Fra : Jacob Bunk Nielsen


Dato : 14-01-10 13:26

"Mogens Hansen" <mogens_h@dk-online.dk> writes:

> Derudover giver det den konkrete værdi af en pointer ikke meget mening at
> gemme i en fil. Den kan bruges en unik identifikation af et objekt, men kan
> bruges som pointer værdi når den læses igen.

Der mangler vist et 'ikke' i ovenstående. Der burde sikkert have stået:

.... men kan IKKE bruges som pointer værdi når den læses igen.

Bare lige for at undgå forvirring i et ellers meget brugbart indlæg.

--
Jacob - www.bunk.cc

acs (18-01-2010)
Kommentar
Fra : acs


Dato : 18-01-10 03:20

tak for forklaringerne og links til de relevante hjemmesider som viste
hvordan man kunne gøre det.
Jeg har bedre styr på forskellene mellem c++ og java nu, og det er
lykkedes mig at serialisere og senere genskabe det objekt jeg havde
brug for at gemme.
/Anders

Søg
Reklame
Statistik
Spørgsmål : 177564
Tips : 31968
Nyheder : 719565
Indlæg : 6408970
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste