2011-09-16 15 views
6

मैं अपने एमएफसी एप्लिकेशन में std :: स्ट्रिंग का उपयोग कर रहा हूं और मैं इसे दस्तावेज़ के Serialize() फ़ंक्शन में संग्रहीत करना चाहता हूं। मैं उन्हें सीएसटींग के रूप में स्टोर नहीं करना चाहता क्योंकि यह वहां अपनी खुद की चीजें लिखता है और मेरा लक्ष्य एक फाइल बनाना है जिसे मैं प्रारूप के बारे में जानता हूं और CString की आवश्यकता के बिना अन्य एप्लिकेशन द्वारा पढ़ा जा सकता है। इसलिए मैं अपने std :: स्ट्रिंग्स को 4 बाइट्स (int) स्ट्रिंग लम्बाई के रूप में स्टोर करना चाहता हूं जिसके बाद स्ट्रिंग युक्त उस आकार के बफर द्वारा स्टोर किया जाना चाहिए।क्या मैं std :: स्ट्रिंग के साथ काम करने के लिए कैरचिव << ऑपरेटर को अधिभारित कर सकता हूं?

void CMyDoc::Serialize(CArchive& ar) 
{ 
    std::string theString; 

    if (ar.IsStoring()) 
    { 
     // TODO: add storing code here 
     int size = theString.size(); 
     ar << size; 
     ar.Write(theString.c_str(), size); 

    } 
    else 
    { 
     // TODO: add loading code here 
     int size = 0; 
     ar >> size; 
     char * bfr = new char[ size ]; 
     ar.Read(bfr, size); 
     theString = bfr; 
     delete [] bfr; 
    } 
} 

उपरोक्त कोड बहुत अच्छा नहीं है और मुझे स्ट्रिंग पढ़ने के लिए एक temp bfr आवंटित करना होगा। सबसे पहले मैं स्ट्रिंग :: स्ट्रिंग में स्ट्रिंग को सीधे temp बफर के बिना पढ़ सकता हूं? दूसरा, क्या मैं < < std :: string/crchive के लिए बफर अधिभारित कर सकता हूं, इसलिए मैं केवल ar < < theString का उपयोग कर सकता हूं? कुल मिलाकर सीआरडी :: स्ट्रिंग को कैरचिव ऑब्जेक्ट का उपयोग करके पढ़ने/लिखने का एक बेहतर तरीका है?

उत्तर

0

यदि आप ऐसी लाइब्रेरी के साथ काम कर रहे हैं जो केवल सी-स्टाइल स्ट्रिंग के साथ काम करता है, तो write directly to the std::string सुरक्षित रूप से कोई रास्ता नहीं है। यह समस्या सी ++ 0x में तय की गई है। तो जैसे

// NOT PORTABLE, don't do this 
theString.resize(size); 
ar.Read(const_cast<char *>(theString.c_str(), size); 

कुछ शायद काम करेंगे, लेकिन यह बाद में कुछ सूक्ष्म, मुश्किल से ट्रैक कीड़े बना सकते हैं। बेशक आपके प्रश्न का तात्पर्य है कि आपने अपना कोड प्रोफाइल किया है और यह पता लगाया है कि बफर बनाना और डेटा को दो बार कॉपी करना वास्तव में आपके कोड में एक बाधा है। यदि आपने नहीं किया है, तो आपको अभी तक अक्षमता के बारे में परेशान नहीं होना चाहिए।

+0

मैंने यह कोशिश की है लेकिन c_str() एक 'const char *' देता है और यह एक समस्या है। मैं शायद इसे 'char *' पर टाइप कर सकता हूं लेकिन यह कुछ हद तक c_str() फ़ंक्शन का उल्लंघन करेगा। – zar

+1

इस प्रकार "यह मत करो" टिप्पणी। आप 'std :: vector ' का उपयोग कर सकते हैं या चूंकि आप एमएफसी भूमि उपयोग में हैं 'CString' – AJG85

1

प्रयास करें:

theString.resize(size); 
ar.Read(&theString[0], size); 

तकनीकी तौर पर &theString[0] एक सन्निहित चरित्र बफर को इंगित करने की गारंटी नहीं है, लेकिन सी ++ समिति एक सर्वेक्षण किया और पाया कि सभी मौजूदा कार्यान्वयन इस तरह से काम करते हैं।

0

मैं तुम्हें एसटीएल दिशानिर्देशों का उल्लंघन और std::string वारिस और अपने खुद के बफर गेटर/सेटर जोड़ सकते हैं लगता है। फिर std :: स्ट्रिंग के लिए कॉपी कन्स्ट्रक्टर को ओवरराइड करें और बफर के स्वामित्व को स्थानांतरित करें।

1

आप अपनी एसटीएल स्ट्रिंग से एक जगह सीएसटींग बना सकते हैं और उसे क्रमबद्ध कर सकते हैं। कुछ की तरह:

CArchive& operator<<(CArchive rhs, string lhs) { 
    CString c_string(lhs.c_str()); 
    rhs << c_string; 
} 
1

इसकी शायद बेहतर डेटा लिखने के लिए:

CString c_string(my_stl_string.c_str(); 
ar << c_string; 

आप यह एक वैश्विक operater अधिभार में तो आप कर सकते हैं यह कर सकते हैं बस

ar << my_c_string; 

कहीं से भी जैसे डाल सकता है विभिन्न कारणों से एक सीएसटींग के रूप में, लेकिन यदि आपको अपनी स्ट्रिंग (m_sString) को एक ASCII वर्ण स्ट्रिंग में परिवर्तित करना है, तो शायद ऐसा कुछ आपके लिए काम करेगा ...

void myclass::Serialize(CArchive & ar) 
{ 
    CHAR* buf; 
    DWORD len; 
    if (ar.IsStoring()) // Writing 
    { 
     len = m_sString.GetLength(); // Instead of null terminated string, store size. 
     ar << len; 
     buf = (CHAR*)malloc(len); 
     WideCharToMultiByte(CP_UTF8, 0, m_sString, len, buf, len, NULL, NULL); // Convert wide to single bytes 
     ar.Write(buf, len); // Write ascii chars 
     free(buf); 
    } 
    else // Reading 
    { 
     ar >> len; 
     buf = (CHAR*)malloc(len); 
     ar.Read(buf, len); // Read ascii string 
     MultiByteToWideChar(CP_UTF8, 0, buf, len, m_sString.GetBufferSetLength(len), len); // Convert ascii bytes to CString wide bytes 
     free(buf); 
    } 
} 
संबंधित मुद्दे