如何从LPCTSTR转换为std :: string?

时间:2011-04-01 12:59:53

标签: c++ string visual-c++

我有一个LPCTSTR,想要调用一个带std::string参数的函数。

我需要做什么转换?

7 个答案:

答案 0 :(得分:16)

冰山一角

LPCTSTR可以是单字节字符串也可以是多字节字符串(取决于编译期间定义的UNICODE常量),而std::string的用户(包括您的函数) )通常用它来保存单字节字符串。

您需要进行两次转换:一次转化为LPCSTR(非UNICODE版),另一次转换为LPCWSTRUNICODE版本)。第一个很简单:

std::string convert(LPCSTR str) {
    return std::string(str);
}

第二个需要首先使用WideCharToMultiByte将其输入参数转换为另一个编码。不要被名称吓到,结果可以是一个单字节的字符串;这取决于CodePage参数。您必须使用代码页进行单字节编码,例如CP_ACP

更新:WideCharToMultiByte示例

请注意,如果输入字符串包含目标编码代码页中不存在的字符,则在技术上不可能准确地转换为单字节编码。由于您提到它将用于文件系统功能,如果文件路径包含此类字符,则转换将不会100%准确,后续函数调用将失败。

std::string MBFromW(LPCWSTR pwsz, UINT cp) {
    int cch = WideCharToMultiByte(cp, 0, pwsz, -1, 0, 0, NULL, NULL);

    char* psz = new char[cch];

    WideCharToMultiByte(cp, 0, pwsz, -1, psz, cch, NULL, NULL);

    std::string st(psz);
    delete[] psz;

   return st;
}

警告经理:上面的示例来自我所处的一些代码,并不是生产级质量。一个明显的缺陷是它不是例外安全的。它也可能杀死所有漂亮的紫色独角兽。仅将其用作示例

完整的编码地狱

赤裸裸的事实是std::string可以用于多字节编码(例如UTF8)就好了 - 你甚至可以用它来保存宽字符串,因为它只是一个二进制安全的字节数组在心里。

问题是适用于std::string的STL函数期望其内容采用单字节编码,如果不是这样,它们将不会产生正确的结果

通过扩展,我们不知道您的std::string参数所需的函数是什么 - 它可能期望以UTF-8编码的字符串。但是“按照惯例”,我假设它也想要一个单字节编码的字符串。

答案 1 :(得分:10)

在一行中:

std::string s = CT2A( lpctstr );

答案 2 :(得分:2)

务实的方法:

     LPCTSTR input;

     std::string s;

#ifdef UNICODE
     std::wstring w;
     w = input;
     s = std::string(w.begin(), w.end()); // magic here
#else
     s = input;
#endif

查看优秀背景的其他答案!

答案 3 :(得分:2)

从您的评论:“我调用的函数将采用std :: string并在调用std :: fstream :: open()时将其用作文件名”

嗯,那是错的。该函数确实应该采用tstring(定义为typedef std::basic_string<TCHAR> tstring)。有许多Windows文件,如果没有Unicode,其名称无法表示。例如,如果\User\<myusername\My Documents\ <myUserName>下的所有文件都包含非ANSI字符(并且您真的不想告诉您的用户他的名字不好!)

但是一旦你改为tstring,它就会奏效。您仍然可以获得相同的std::fstream对象。

答案 4 :(得分:1)

LPCTSTR是一个Windows定义,其读取类似于“指向const字符类型字符串的长指针”。我不确定T代表什么,但它与项目的字符集有关。

如果您的项目使用Unicode字符集,则此类型为const wchar_t*,每个字符使用两个字节。如果您的项目使用多字节字符字符集,则此类型为const char*,每个字符使用一个字节。

您项目的字符集很可能是Unicode,因此LPCTSTRconst wchar_t*。由于std::string每个字符使用一个字节,因此每个字符串不能保存这两个字节。但是,std::wstring可以。

如果您需要将const wchar_t*转换为const char*以允许将其分配给字符串,则可以使用wcstombs等函数执行此操作。如果您在项目中包含ATL(特别是atlconv.h),它会提供宏来更轻松地执行此操作:

USES_CONVERSION;
const wchar_t* = L"Wide string";
std::string str = W2A(value);

答案 5 :(得分:1)

这段代码应该从LPWSTR转换为char * / std :: string

LPWSTR input = L"whatever";
int cSize = WideCharToMultiByte (CP_ACP, 0, input, wcslen(input), NULL, 0, NULL, NULL);
std::string output(static_cast<size_t>(cSize), '\0');
WideCharToMultiByte (CP_ACP, 0, input, wcslen(input),
                       reinterpret_cast<char*>(&output[0]), cSize, NULL, NULL);

并且此代码段应该从单字节std :: string转换为LPWSTR

std::string input = "whatever";
//computing wchar size:
int wSize = MultiByteToWideChar (CP_ACP, 0, (LPCSTR) input.c_str (), -1, 0, 0);

//allocating memory for wchar:
LPWSTR output = new WCHAR[wSize];

//conversion from string to LPWSTR:
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED , (LPCSTR) input.c_str (), -1, output, wSize);

答案 6 :(得分:0)

我不知道这个solution是否可以帮到你。