2008-11-03 31 views
63

CString khá tiện dụng, trong khi std::string tương thích hơn với vùng chứa STL. Tôi đang sử dụng hash_map. Tuy nhiên, hash_map không hỗ trợ CString làm khóa, vì vậy tôi muốn chuyển đổi CString thành std::string.Làm thế nào để chuyển đổi CString và :: std :: string :: std :: wstring với nhau?

Viết hàm CString có vẻ mất nhiều thời gian.

CString -----> std::string 

Tôi làm cách nào để thực hiện việc này?

std::string -----> CString: 

inline CString toCString(std::string const& str) 
{ 
    return CString(str.c_str()); 
} 

Tôi có đúng không?


EDIT:

Dưới đây là câu hỏi:

Làm thế nào tôi có thể chuyển đổi wstring, CString với nhau?

//wstring -> CString, 
std::wstring src; 
CString result(src.c_str()); 
//CString->wstring. 
CString src; 
::std::wstring des(src.GetString()); 

mọi sự cố không?

Làm cách nào để chuyển đổi std::wstring, std::string cho nhau?

+3

Tôi sẽ không làm điều này ... Sử dụng hai loại dây khác nhau là đủ xấu, nhưng phải chuyển đổi mỗi khi bạn làm điều gì đó với bản đồ? Nghe thật khủng khiếp. Chỉ cần nhất quán và sử dụng std :: string. Nếu vì một lý do nào đó bạn thực sự nghĩ rằng CString là tốt hơn, sau đó xác định hàm băm cho nó để hash_map của bạn có thể sử dụng nó, điều này tốt hơn gấp đôi sự khó hiểu trong mã của bạn. – GManNickG

+2

Trên thực tế, Nếu tất cả các mã được viết bởi bản thân mình, nó sẽ nhất quán, nhưng có một số dự án mở rộng như sqlite tự do được sử dụng. Tôi không thể sửa đổi mã đó. – user25749

Trả lời

78

Theo CodeGuru:

CString-std::string:

CString cs("Hello"); 
std::string s((LPCTSTR)cs); 

NHƯNG:std::string có thể không phải lúc nào xây dựng từ một LPCTSTR. tức là mã sẽ thất bại đối với các bản dựng UNICODE.

Như std::string có thể xây dựng chỉ từ LPSTR/LPCSTR, một lập trình viên sử dụng VC++ 7.x hoặc tốt hơn có thể sử dụng các lớp học chuyển đổi như CT2CA như một trung gian.

CString cs ("Hello"); 
// Convert a TCHAR string to a LPCSTR 
CT2CA pszConvertedAnsiString (cs); 
// construct a std::string using the LPCSTR input 
std::string strStd (pszConvertedAnsiString); 

std::string to CString: (Từ Visual Studio's CString FAQs...)

std::string s("Hello"); 
CString cs(s.c_str()); 

CStringT có thể xây dựng từ cả hai nhân vật hoặc rộng ký tự chuỗi. tức là nó có thể chuyển đổi từ char* (ví dụ: LPSTR) hoặc từ wchar_t* (LPWSTR).

Nói cách khác, char-chuyên môn (của CStringT) tức là CStringA, wchar_t -specilization CStringW, và TCHAR -specialization CString thể được xây dựng từ một trong hai char hoặc rộng ký tự, null chấm dứt (null-chấm dứt là rất quan trọng ở đây) nguồn chuỗi.
Althoug IInspectable sửa đổi các "null-chấm dứt" phần in the comments:

NUL-chấm dứt không cần.
CStringT có các trình tạo chuyển đổi lấy một đối số chiều dài rõ ràng. Điều này cũng có nghĩa là bạn có thể tạo các đối tượng CStringT từ các đối tượng std::string với các ký tự được nhúng NUL.

+2

Errr ... bạn được chào đón :) Cảm ơn Siddhartha Rao đã giải thích chi tiết. – VonC

+0

Đoạn cuối cùng không hoàn toàn chính xác. 'NUL'-chấm dứt là không cần thiết. ['CStringT'] (http://msdn.microsoft.com/en-us/library/cws1zdt8.aspx) có các hàm tạo chuyển đổi lấy một đối số chiều dài rõ ràng. Điều này cũng có nghĩa là bạn có thể xây dựng các đối tượng 'CStringT' từ các đối tượng' std :: string' với các ký tự 'NUL' được nhúng. – IInspectable

+0

@IInspectable điểm tốt. Tôi đã bao gồm bình luận của bạn trong câu trả lời cho khả năng hiển thị nhiều hơn. – VonC

33

Giải quyết điều đó bằng cách sử dụng std::basic_string<TCHAR> thay vì std::string và nó sẽ hoạt động tốt bất kể cài đặt ký tự của bạn.

+2

Phương pháp này đơn giản hơn – user25749

+5

Tôi thích typedef để thuận tiện và quen thuộc: 'typedef std :: basic_string tstring' –

-1

Nếu bạn muốn chuyển đổi dễ dàng giữa các loại chuỗi khác, có lẽ lớp học _bstr_t sẽ phù hợp hơn? Nó hỗ trợ hội tụ giữa char, wchar_tBSTR.

+1

-1' CString' đã thực hiện tất cả các chuyển đổi bạn đặt tên. Và nó cũng đã 3 năm trước. Không có điểm trong đề xuất một loại có nghĩa là để sử dụng trong môi trường COM. – IInspectable

4

Nếu bạn muốn một cái gì đó thêm C++ - như, đây là những gì tôi sử dụng. Mặc dù nó phụ thuộc vào Boost, đó là chỉ cho trường hợp ngoại lệ. Bạn có thể dễ dàng loại bỏ những người rời khỏi nó để chỉ phụ thuộc vào STL và cuộc gọi API WideCharToMultiByte() Win32.

#include <string> 
#include <vector> 
#include <cassert> 
#include <exception> 

#include <boost/system/system_error.hpp> 
#include <boost/integer_traits.hpp> 

/** 
* Convert a Windows wide string to a UTF-8 (multi-byte) string. 
*/ 
std::string WideStringToUtf8String(const std::wstring& wide) 
{ 
    if (wide.size() > boost::integer_traits<int>::const_max) 
     throw std::length_error(
      "Wide string cannot be more than INT_MAX characters long."); 
    if (wide.size() == 0) 
     return ""; 

    // Calculate necessary buffer size 
    int len = ::WideCharToMultiByte(
     CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), 
     NULL, 0, NULL, NULL); 

    // Perform actual conversion 
    if (len > 0) 
    { 
     std::vector<char> buffer(len); 
     len = ::WideCharToMultiByte(
      CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), 
      &buffer[0], static_cast<int>(buffer.size()), NULL, NULL); 
     if (len > 0) 
     { 
      assert(len == static_cast<int>(buffer.size())); 
      return std::string(&buffer[0], buffer.size()); 
     } 
    } 

    throw boost::system::system_error(
     ::GetLastError(), boost::system::system_category); 
} 
5

Hiệu quả hơn để chuyển đổi CString thành std::string bằng cách sử dụng chuyển đổi có độ dài được chỉ định.

CString someStr("Hello how are you"); 
std::string std(somStr, someStr.GetLength()); 

Trong vòng lặp chặt chẽ, điều này giúp cải thiện hiệu suất đáng kể.

+1

Tôi gặp lỗi khi sử dụng: 'không thể chuyển đổi tham số 1 từ 'CString' thành 'const std :: basic_string <_Elem, _Traits, _Alloc> &'' –

1

trình cho tôi:

std::wstring CStringToWString(const CString& s) 
{ 
    std::string s2; 
    s2 = std::string((LPCTSTR)s); 
    return std::wstring(s2.begin(),s2.end()); 
} 

CString WStringToCString(std::wstring s) 
{ 
    std::string s2; 
    s2 = std::string(s.begin(),s.end()); 
    return s2.c_str(); 
} 
1

Đây là một theo dõi câu trả lời của Sal, nơi ông/bà cung cấp các giải pháp:

CString someStr("Hello how are you"); 
std::string std(somStr, someStr.GetLength()); 

này rất hữu ích cũng khi chuyển đổi một tổ chức phi điển hình C -String to a std :: string

Một trường hợp sử dụng cho tôi đã có một mảng char được cấp phát trước (như C-String), nhưng nó không phải là NUL chấm dứt. (tức là thông báo SHA). Cú pháp trên cho phép tôi chỉ định độ dài của thông báo SHA của mảng char sao cho chuỗi std :: không phải tìm kiếm ký tự kết thúc NUL char, có thể có hoặc không có ở đó.

Chẳng hạn như:

unsigned char hashResult[SHA_DIGEST_LENGTH];  
auto value = std::string(reinterpret_cast<char*>hashResult, SHA_DIGEST_LENGTH); 
+0

Có lẽ, sẽ tốt hơn nếu bạn chỉnh sửa câu trả lời của Sal kèm theo sửa đổi của bạn hoặc nhận xét về câu trả lời của Sal? – Kmeixner

+0

Tôi đã thử ... nhưng stackoverflow không cấp cho tôi khả năng thực hiện và chỉnh sửa. – Neil

1

này hoạt động tốt:

//Convert CString to std::string 
inline std::string to_string(const CString& cst) 
{ 
    return CT2A(cst.GetString()); 
} 
0

Tất cả các câu trả lời khác không địa chỉ khá gì tôi đang tìm kiếm mà là để chuyển đổi CString khi đang bay như trái ngược với lưu trữ kết quả trong một biến.

Giải pháp tương tự như trên nhưng chúng tôi cần thêm một bước nữa để khởi tạo một đối tượng không tên. Tôi đang minh họa bằng một ví dụ. Đây là chức năng của tôi cần std::string nhưng tôi có CString.

void CStringsPlayDlg::writeLog(const std::string &text) 
{ 
    std::string filename = "c:\\test\\test.txt"; 

    std::ofstream log_file(filename.c_str(), std::ios_base::out | std::ios_base::app); 

    log_file << text << std::endl; 
} 

Cách gọi điện thoại khi bạn có CString?

std::string firstName = "First"; 
CString lastName = _T("Last"); 

writeLog(firstName + ", " + std::string(CT2A(lastName)));  

Lưu ý rằng dòng cuối cùng không phải là một thợ đúc chư trực tiếp nhưng chúng tôi đang tạo ra một đối tượng vô danh std::string và cung cấp CString qua constructor của nó.

0

Tại sao không chỉ truyền từ CString đến CStringA bên trong một constructor string?

 CString s1("SomeString"); 
     string s2((CStringA)s1); 
Các vấn đề liên quan