2011-09-16 39 views
6

Tôi đang sử dụng std :: string trong ứng dụng MFC của mình và tôi muốn lưu trữ nó trong hàm Serialize() của doc. Tôi không muốn lưu trữ chúng như là CString bởi vì nó viết các công cụ riêng của nó trong đó và mục tiêu của tôi là tạo một tệp mà tôi biết định dạng và có thể được đọc bởi ứng dụng khác mà không cần CString. Vì vậy, tôi muốn lưu trữ của tôi std :: strings như 4 byte (int) chuỗi chiều dài theo sau là bộ đệm của kích thước có chứa chuỗi.Tôi có thể quá tải toán tử CArchive << để làm việc với std :: string không?

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

Mã trên không tuyệt vời và tôi phải phân bổ một temp bfr để đọc chuỗi. Trước tiên tôi có thể đọc chuỗi trực tiếp vào std :: string mà không có bộ đệm tạm thời? Thứ hai tôi có thể quá tải bộ đệm < < cho std :: string/CArchive vì vậy tôi chỉ có thể sử dụng ar < < theString? Nói chung là có một cách tốt hơn để đọc/ghi std :: string bằng cách sử dụng đối tượng CArchive?

Trả lời

0

Nếu bạn đang làm việc với thư viện chỉ hoạt động với chuỗi kiểu c, không có cách nào an toàn write directly to the std::string. Vấn đề đó được sửa trong C++ 0x. Vì vậy, một cái gì đó giống như

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

lẽ sẽ làm việc, nhưng nó có thể tạo ra một số tinh tế, khó theo dõi lỗi sau này. Tất nhiên câu hỏi của bạn ngụ ý rằng bạn đã lược tả mã của mình và nhận ra rằng việc tạo bộ đệm và sao chép dữ liệu hai lần thực sự là một nút cổ chai trong mã của bạn. Nếu bạn chưa có, thì bạn không nên lo lắng về sự thiếu hiệu quả.

+0

Tôi đã thử điều này nhưng c_str() trả về 'const char *' và đó là một vấn đề. Tôi có lẽ có thể typecast nó chỉ đơn giản là 'char *' nhưng điều đó sẽ phần nào vi phạm các chức năng c_str(). – zar

+1

Do đó, nhận xét "không làm điều này". Bạn có thể sử dụng 'std :: vector ' hoặc vì bạn đang sử dụng đất MFC 'CString' – AJG85

1

Hãy thử:

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

Về mặt kỹ thuật &theString[0] không được bảo đảm để trỏ đến một bộ đệm ký tự liền kề, nhưng ++ ủy ban C đã làm một cuộc khảo sát và thấy rằng tất cả hiện thực hiện làm việc theo cách này.

0

Tôi cho rằng bạn có thể vi phạm nguyên tắc STL và kế thừastd::string và thêm bộ đệm/bộ đệm của riêng bạn. Sau đó ghi đè lên hàm tạo bản sao cho std :: string và chuyển quyền sở hữu của bộ đệm.

1

Bạn có thể tạo CString tại chỗ từ chuỗi stl của bạn và tuần tự hóa chuỗi đó. Một cái gì đó như:

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

Bạn có thể đặt điều này trong một tình trạng quá tải operater toàn cầu vì thế nó có thể bạn có thể chỉ

ar << my_c_string; 

từ bất cứ nơi nào ví dụ:

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

của nó có lẽ tốt hơn để ghi dữ liệu như một CString vì nhiều lý do, nhưng nếu bạn phải chuyển đổi chuỗi của bạn (m_sString) thành một chuỗi ký tự ASCII, có thể một cái gì đó như thế này sẽ làm việc cho bạn ...

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); 
    } 
} 
Các vấn đề liên quan