2010-11-30 16 views
5

मैं जानता हूँ कि मैं उपयोग कर सकते हैं:ग बचाने के लिए और structs में संकेत के साथ लोड खेल ++

MyGame game; // the game object 
// 

ofstream out("mygame.bin", ios::binary); 
out.write((char *)&game, sizeof(MyGame)); 

बचाने के लिए और खेल लोड करने के लिए है, लेकिन क्या अगर मैं MyGame संरचना के भीतर संकेत है? क्या पॉइंटर्स सिर्फ सहेजे जाएंगे, लेकिन डेटा को इंगित नहीं करेगा?

और: इसे कैसे हल करें?

उत्तर

5

पर अनुक्रमण के बारे में और अधिक पढ़ आप न सिर्फ एक धारा की ओर इशारा लिख ​​सकते हैं और उम्मीद करते हैं यह जादुई किया जा सकता है। आपको अपनी ऑब्जेक्ट्स में सेव/लोड विधियों को लागू करने की आवश्यकता है। उदा:

class Serializable 
{ 
    virtual void save(std::ofstream& _out) const = 0; 
    virtual void load(std::ifstream& _in) = 0; 
}; // eo class Serializable 


// some game object 
class MyObject : public Serializable 
{ 
    int myInt; 
    std::string myString; 

    virtual void save(std::ofstream& _out) const 
    { 
     _out << myInt << myString; 
    }; // eo save 

    virtual void load(std::ifstream& _in) 
    { 
     _in >> myInt >> myString; 
    }; // eo load 
}; // eo class SomeObject 

class MyGame : public Serializable 
{ 
    MyObject a; 
    MyObject b; 

    virtual void save(std::ofstream& _out) const 
    { 
     a.save(_out); 
     b.save(_out); 
    }; // eo save 

    virtual void load(std::ifstream& _in) 
    { 
     a.load(_in); 
     b.load(_in); 
    }; // eo load 
}; // eo class MyGame 
+0

यह वास्तव में बाइनरी नहीं है?;) – Nim

+0

भी, एक धारा के लिए फ़ील्ड को अलग करने के लिए एक विभाजक की आवश्यकता होती है (आमतौर पर एक स्थान), इस उदाहरण में यह स्ट्रीम आउट ऑपरेशन में अनुपलब्ध है, इसलिए जब आप पूर्णांक को पढ़ने का प्रयास करते हैं तो ऑपरेशन में स्ट्रीम बस अपवाद फेंक देगी (I सोचो, मैंने इसका परीक्षण नहीं किया है इसलिए मैं गलत हो सकता हूं) – Nim

+0

यह इसे काट नहीं देगा। सबसे पहले, आप यहां "धोखाधड़ी" कर रहे हैं क्योंकि आप ओपी की आवश्यकता के अनुसार किसी भी पॉइंटर्स को क्रमबद्ध नहीं कर रहे हैं। साथ ही, आप यह मान रहे हैं कि << and >> ऑपरेटर चाल चलेंगे, जब यह प्राइमेटिव्स के क्रमबद्धीकरण को नियंत्रित करने के लिए अधिक मजबूत होता है (उदाहरण के लिए नेटवर्क पर डेटा संचारित करने के संबंध में एचटीटीएल() और ntohl() के साथ क्या किया जाता है) । – Jon

1

आप ऑपरेटर धारा बाहर (<<) ओवरलोड और प्रत्येक व्यक्ति के क्षेत्र (और इसके विपरीत)

संपादित बाहर स्ट्रीम कर सकते हैं: यहाँ एक पूरा उदाहरण है ...

#include <iostream> 
#include <fstream> 
#include <map> 

using namespace std; 

template <typename T> 
void serialize(ostream& str, const T& field) 
{ 
    str.rdbuf()->sputn(reinterpret_cast<const char*>(&field), sizeof(T)); 
} 

template <typename T> 
void deserialize(istream& str, T& field) 
{ 
    str.rdbuf()->sgetn(reinterpret_cast<char*>(&field), sizeof(T)); 
} 

class MyGame 
{ 
public: 
MyGame() : a(), b() {} 
MyGame(int av, int bv) : a(av), b(bv) {} 

friend ostream& operator<<(ostream& str, MyGame const& game); 
friend istream& operator>>(istream& str, MyGame& game); 

    int getA() const { return a; } 
    int getB() const { return b; } 

private: 
int a; 
int b; 
}; 

ostream& operator<<(ostream& str, MyGame const& game) 
{ 
    serialize(str, game.a); 
    serialize(str, game.b); 
    return str; 
} 

istream& operator>>(istream& str, MyGame& game) 
{ 
    deserialize(str, game.a); 
    deserialize(str, game.b); 
    return str; 
} 

int main(void) 
{ 
    { 
    ofstream fout("test.bin", ios::binary); 
    MyGame game(10, 11); 
    fout << game; 
    } 

    { 
    ifstream fin("test.bin", ios::binary); 
    MyGame game; 
    fin >> game; 
    cout << "game.a: " << game.getA() << ", game.b: " << game.getB() << endl; 
    } 

    return 0; 
} 

आप को समझना चाहिए हालांकि इस दृष्टिकोण के साथ मुद्दे, जैसे परिणामी फ़ाइल प्लेटफ़ॉर्म विशिष्ट (यानी गैर पोर्टेबल) आदि होगी

0

game.serialize(out); आज़माएं। अपने serialize सदस्य समारोह में अपने सूचक सदस्यों के serialize कॉल करें।

0

प्रति प्रकार एक क्रमबद्ध कार्य करें जो लगातार होने की आवश्यकता है।
प्रत्येक सदस्य के लिए इसे कॉल करें।

यह वास्तव में नेटवर्क पर क्रमबद्ध करने या डीबग-प्रयोजनों के लिए विज़ुअलाइज़ करने जैसा ही है।

boost.serialize आपकी मदद कर सकता है।

2

मान लीजिए कि आपने चार * कलाकारों को ओवरराइड नहीं किया है, हां यह शायद केवल सूचक को ही बचाएगा, न कि डेटा।

आपको अपनी वस्तु का सीरियलाइजेशन चाहिए। आप ऑब्जेक्ट की स्थिति को थोड़ी सी स्ट्रीम में मार्शल करने और इसे लिखने के लिए एक विधि प्रदान कर सकते हैं। और आपको राज्य को वापस बहाल करने के लिए विधि भी होनी चाहिए।

आप wikipedia

+0

जैसा कि नीचे बताया गया है कि आपके क्रमिकरण और पुनर्स्थापना विधियों को << and >> ऑपरेटर ओवरराइड किया जा सकता है! –

1

बूस्ट एक serialization library है, गहरी सूचक के लिए समर्थन को बचाने और बहाल करने और उसे साझा आंकड़ों के संकेत के समुचित क्रमबद्धता में बनाया गया है।

यह एक नहीं बल्कि विस्तृत पुस्तकालय है, लेकिन आप इतना कोड अपनी खुद की परियोजनाओं में इसे का उपयोग शुरू करने के लिए लिखने के लिए की जरूरत नहीं है। मेरी राय में सबसे सरल क्रमिकरण आवश्यकताओं के अलावा कुछ भी सीखने के प्रयास के लायक है।

0

"अनुभवहीन" क्रमबद्धता सिर्फ उदासीनता है कि संकेत के मूल्य कभी नहीं काम करने के लिए, क्योंकि जब deserializing, उन संकेत अमान्य होने की जा रही है।

इस तरह की समस्या के लिए सामान्य दृष्टिकोण इस तरह जाना होगा:

  1. प्रत्येक वस्तु है कि अपने खेल में श्रृंखलाबद्ध किया जा सकता है एक serialize() आभासी समारोह को लागू (मैं यह सोचते हैं रहा हूँ इस तरह के सभी वस्तुओं अंततः से निकाले जाते हैं जाएगा है एक ही आधार वर्ग)।
  2. आधार वर्ग get_serialized_id() सार्वजनिक फ़ंक्शन लागू करें।यह फ़ंक्शन प्रत्येक ऑब्जेक्ट इंस्टेंस के लिए एक अद्वितीय आईडी उत्पन्न करने के लिए एक स्थिर ऑटो-वृद्धि वाले चर का उपयोग करेगा, लेकिन केवल पहली बार इसे कॉल किया जाएगा (बाद की कॉल केवल मौजूदा मान वापस कर देगी)।
अब

, जब serializing:

  1. प्रारंभ एक std::map<int, YourBaseClass*> साथ। कुंजी के लिए get_serialized_id() द्वारा दिए गए मान का उपयोग करके, इस मानचित्र पर अपनी game ऑब्जेक्ट जोड़ें।
  2. जबकि नक्शा वस्तुओं है कि अभी तक धारावाहिक नहीं किया गया है:
    • पहली ऐसी वस्तु है।
    • अपने get_serialized_id() को क्रमबद्ध करें।
    • serialize() के लिए इसके कार्यान्वयन को कॉल करके इसे क्रमबद्ध करें। क्या यह सामान्य रूप से अपने आदिम डेटा को जारी रखता है। पॉइंटर्स के माध्यम से उपलब्ध डेटा के लिए, प्रत्येक ऑब्जेक्ट पर get_serialized_id() पर कॉल करें और उससे लौटाई गई संख्या को क्रमबद्ध करें। साथ ही, उस ऑब्जेक्ट को मानचित्र में जोड़ें।

यह वस्तुओं का एक समूह धारावाहिक की जा रही है (एक "यादृच्छिक" क्रम में) हर एक के "यादृच्छिक" आईडी के साथ का परिणाम देगा।

जब deserializing: एक std::map<int, YourBaseClass*> साथ

  1. प्रारंभ। अपनी सहेजी गई फ़ाइल में पहला आइटम पढ़ें।
  2. प्रत्येक ऑब्जेक्ट के लिए इस ऑब्जेक्ट द्वारा इंगित किया गया है, तो आप एक अद्वितीय आईडी जानते हैं (यही वह है जिसे आप पॉइंटर के बजाय क्रमबद्ध करते हैं)। इस आईडी के साथ सहेजी गई फाइल से आइटम लाएं और इसे deserialize करें।
  3. तब तक ऐसा करें जब तक कि सभी आइटम सहेजे गए फ़ाइल से प्राप्त नहीं किए जाते हैं और deserialized।
  4. चूंकि प्रत्येक आइटम की उपरोक्त चरण 3 में इसकी सभी निर्भरताएं अव्यवस्थित हैं, इसे किसी ऑब्जेक्ट के रूप में तुरंत चालू करें और इसे मानचित्र में जोड़ें।
  5. इससे आपको किसी आइटम की आईडी दिए गए मानचित्र से पॉइंटर पकड़ने में मदद मिलेगी, जिसे आप अब इस आइटम पर निर्भर वस्तुओं के पॉइंटर सदस्यों को सेट करने के लिए उपयोग कर सकते हैं।
  6. जब रिकर्सन समाप्त होता है, तो मानचित्र में अंतिम वस्तु आपके मुख्य "गेम" ऑब्जेक्ट होगी जो इसके सभी पॉइंटर्स जाने के लिए तैयार होगी।
0

आप क्या उथले प्रतिलिपि, यदि आप अपने MyGame कक्षा में संकेत दिए गए है, तो एक गहरी प्रतिलिपि एक MUST है !. मैं MyGame के अंदर फ़ंक्शन या फ़ंक्शियंस का एक सेट लागू करने का सुझाव देता हूं जो फ़ाइल में अपना डेटा सहेजने का ख्याल रखेगा, और आपको केवल इसे कॉल करने की आवश्यकता होगी।

0

सभी को तेज़ और अच्छे उत्तरों के लिए धन्यवाद, लेकिन मेरा एक दोस्त (जो इस पर मेरी मदद कर रहा है) ने मुझे बताया कि हमें इसे किसी अन्य तरीके से करना चाहिए।

मैं बस वस्तु की मूल बातें सहेजता हूं और हम बाकी को एक फ़ंक्शन में फिर से बनाते हैं।

यह कार्ड-गेम है और कार्ड के ढेर को बचाने के लिए हम केवल कार्ड की आईडी सहेजेंगे (ऑब्जेक्ट्स नहीं) और फ़ाइल से आईडी में पढ़ने पर प्रत्येक कार्ड को फिर से शुरू करना होगा।

संबंधित मुद्दे