2011-09-16 7 views
6

MFC uygulamasında std :: string kullanıyorum ve bunu doc's Serialize() işlevinde saklamak istiyorum. Bunları CString olarak saklamak istemiyorum çünkü kendi yazılarını orada yazıyor ve amacım CString'e gerek duymadan diğer uygulamaların formatını bildiğim ve okuyabileceğim bir dosya oluşturmak. Bu yüzden std :: string'leri 4 bayt (int) string uzunluğu olarak saklamak ve ardından dizeyi içeren bu boyuttaki arabelleği saklamak istiyorum.Std :: string ile çalışmak için CArchive << operatörünü aşırı yükleyebilir miyim?

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; 
    } 
} 

Yukarıdaki kod büyük değildir ve dizeyi okumak için bir geçici bfr ayırmak zorundayım. İlk olarak, temp tamponu olmaksızın dizeyi doğrudan std :: string dosyasına okuyabilir miyim? İkinci olarak, < < < arabelleğini std :: string/CArchive için aşırı yükleyebilirim, bu yüzden sadece < < theString? Genel olarak, CArchive nesnesini kullanarak std :: string okumak/yazmak için daha iyi bir yol var mı?

cevap

0

Yalnızca c stili strings ile çalışan bir kitaplık ile çalışıyorsanız, güvenli bir şekilde write directly to the std::string güvenliğini sağlamanın bir yolu yoktur. Bu sorun C++ 0x ile giderilmiştir. Yani

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

gibi bir şey belki işe yarar, ancak daha sonra bazı ince, zor pist böcek yaratabilir. Elbette sorunuz, kodunuzu belirlediğinizi ve arabelleği oluşturup iki kez kopyalamanın aslında kodunuzdaki bir darboğaz olduğunu anlamanızı gerektirir. Eğer yapmadıysanız, o zaman henüz verimsizlikler hakkında endişelenmemelisiniz.

+0

Bunu denedim ama c_str() bir 'const char *' döndürüyor ve bu bir sorun. Muhtemelen 'char *' olarak yazabilirim ama bu c_str() işlevini bir şekilde ihlal eder. – zar

+1

Böylece "bunu yapma" yorumu. 'Std :: vector ' veya MFC arazi kullanımı 'CString' kullandığınız için kullanabilirsiniz. – AJG85

1

Dene:

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

Teknik &theString[0] bitişik bir karakter tampon işaret garanti edilmez, ancak C++ komitesi bir anket yaptı ve tüm mevcut uygulamalar bu şekilde çalışan bulundu.

0

Sanırım STL yönergelerini ve numaralıstd::string öğelerini ihlal edebilir ve kendi arabellek alıcınızı/ayarlayıcınızı ekleyebilirsiniz. Daha sonra std :: string için kopya oluşturucuyu geçersiz kılın ve arabelleğin sahipliğini aktarın.

1

Stl dizinizden bir in-site CString oluşturabilir ve bunu seri hale getirebilirsiniz. Bir şey gibi:

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

Onun muhtemelen daha iyi veri yazmak için: yapabilirsiniz olabildiğince böylece

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

Sen mesela yerden küresel Operater aşırı sadece

ar << my_c_string; 

bu koyabilirsiniz çeşitli nedenlerle bir CString olarak, ancak String (m_sString) bir ASCII karakter dizesine dönüştürmek zorundaysanız, belki de bunun gibi bir şey sizin için çalışacaktır ...

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); 
    } 
}