C++ 如何从 LPCTSTR 转换为 std::string?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5513718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I convert from LPCTSTR to std::string?
提问by GrahamS
I have an LPCTSTR
and want to call a function that takes a std::string
parameter.
我有一个LPCTSTR
并想调用一个带std::string
参数的函数。
What conversion do I need to do?
我需要做什么转换?
回答by Jon
Tip of the iceberg
冰山一角
LPCTSTR
can be either a single-byte or a multibyte string (depends on the UNICODE
constant being defined during compilation or not), while std::string
's users (including your function) normally use it to hold a single-byte string.
LPCTSTR
可以是单字节或多字节字符串(取决于UNICODE
编译期间定义的常量与否),而std::string
的用户(包括您的函数)通常使用它来保存单字节字符串。
You 'd need two conversions: one for LPCSTR
(non-UNICODE
build) and one for LPCWSTR
(UNICODE
build). The first one is simple:
您需要两种转换:一种用于LPCSTR
(非UNICODE
构建)和一种用于LPCWSTR
(UNICODE
构建)。第一个很简单:
std::string convert(LPCSTR str) {
return std::string(str);
}
The second one needs its input parameter to be converted to another encoding first with WideCharToMultiByte
. Do not be alarmed by the name, the result canbe a single-byte char string; that depends on the CodePage
parameter. You will have to use a codepage for a single-byte encoding, such as CP_ACP
.
第二个需要首先将其输入参数转换为另一种编码WideCharToMultiByte
。不要被名字吓到,结果可以是一个单字节的char字符串;这取决于CodePage
参数。您必须使用代码页进行单字节编码,例如CP_ACP
.
Update: WideCharToMultiByte
example
更新:WideCharToMultiByte
示例
Be aware that accurately converting to a single-byte encoding is technically impossible if the input string contains characters not existing in the target encoding's code page.Since you mention it's going to be for filesystem functions, if the file path contains such characters the conversion will not be 100% accurate and the subsequent function calls will fail.
请注意,如果输入字符串包含目标编码的代码页中不存在的字符,那么准确地转换为单字节编码在技术上是不可能的。由于您提到它将用于文件系统函数,如果文件路径包含此类字符,则转换将不会 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;
}
Caveat emptor:The example above is from some code I had lying around and is not production-grade quality. The one immediately obvious flaw is that it is not exception-safe. It might also kill all the nice purple unicorns. Use it only as an example.
警告:上面的例子来自我身边的一些代码,不是生产级质量。一个显而易见的缺陷是它不是异常安全的。它也可能杀死所有漂亮的紫色独角兽。仅将其用作示例。
The full encoding hell
完整的编码地狱
The naked truth is that std::string
can be used for multibyte encodings (such as UTF8) just fine -- you can even use it to hold wide-char strings, since it's just a binary-safe array of bytes at heart.
赤裸裸的事实是,它std::string
可以很好地用于多字节编码(例如 UTF8)——您甚至可以用它来保存宽字符字符串,因为它本质上只是一个二进制安全的字节数组。
The problem is that the STL functions that apply to std::string
expect its contents to be in a single-byte encoding, and they won't produce correct results if this is not true.
问题是STL 函数适用于std::string
期望其内容为单字节编码,如果这不是真的,它们将不会产生正确的结果。
By extension, we don't know what your function that takes an std::string
parameter expects-- it might expect a string encoded in UTF-8. But "by convention", I 'm assuming it also wants a single-byte-encoded string.
通过扩展,我们不知道带std::string
参数的函数期望什么——它可能期望以 UTF-8 编码的字符串。但是“按照惯例”,我假设它也需要一个单字节编码的字符串。
回答by Inverse
in one line:
在一行中:
std::string s = CT2A( lpctstr );
回答by MSalters
From your comment: "The function I am calling will take the std::string and use it as the filename when calling std::fstream::open()"
来自您的评论:“我正在调用的函数将采用 std::string 并在调用 std::fstream::open() 时将其用作文件名”
Well, that's wrong. The function really should take a tstring
(defined as typedef std::basic_string<TCHAR> tstring
). There are many Windows files whose name cannot be represented without Unicode. For instance, all files under \User\<myusername\My Documents\
if <myUserName>
contains a non-ANSI character (and you really don't want to tell your user that he has a bad name!)
嗯,这是错误的。该函数确实应该采用tstring
( 定义为typedef std::basic_string<TCHAR> tstring
)。有许多 Windows 文件的名称不能在没有 Unicode 的情况下表示。例如,\User\<myusername\My Documents\
if下的所有文件都<myUserName>
包含一个非 ANSI 字符(而且您真的不想告诉您的用户他的名字不好!)
But once you've changed to tstring
, it just works. You still get the same std::fstream
object.
但是一旦您更改为tstring
,它就会起作用。你仍然得到相同的std::fstream
对象。
回答by Collin Dauphinee
LPCTSTR
is a Windows define that reads as something like 'long pointer to a const character-type string.' I'm not actually sure what the T stands for, but it has to do with the project's character set.
LPCTSTR
是一个 Windows 定义,读作类似于“指向 const 字符类型字符串的长指针”。我实际上不确定 T 代表什么,但它与项目的字符集有关。
If your project is using the Unicode character set, this type is a const wchar_t*
, which uses two bytes per character. If your project is using the multi-byte characters character set, this type is a const char*
, which uses one byte per character.
如果您的项目使用 Unicode 字符集,则此类型为 a const wchar_t*
,每个字符使用两个字节。如果您的项目使用多字节字符字符集,则此类型为const char*
,每个字符使用一个字节。
Most likely your project's character set is Unicode, so LPCTSTR
is a const wchar_t*
. Since std::string
uses one byte per character, it can't hold this two byte per character string. std::wstring
can, however.
最有可能你的项目的字符集是Unicode,所以LPCTSTR
是一个const wchar_t*
。由于std::string
每个字符使用一个字节,因此每个字符串不能容纳这两个字节。std::wstring
不过可以。
If you need to convert the const wchar_t*
to a const char*
to allow it to be assigned to a string, you can use functions like wcstombs
to do this. If you're including ATL (specifically atlconv.h
) in your project, it provides macros to do this more easily:
如果您需要将 the 转换const wchar_t*
为 aconst char*
以允许将其分配给字符串,则可以使用类似的函数wcstombs
来执行此操作。如果您在项目中包含 ATL(特别是atlconv.h
),它会提供宏来更轻松地执行此操作:
USES_CONVERSION;
const wchar_t* = L"Wide string";
std::string str = W2A(value);
回答by sehe
Pragmatic approach:
务实的方法:
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
See other answers for excellent backgrounders!
查看优秀背景人员的其他答案!
回答by marchelbling
This snippet of code should do conversion from LPWSTR to char*/std::string
这段代码应该做从 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), '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);
');
WideCharToMultiByte (CP_ACP, 0, input, wcslen(input),
reinterpret_cast<char*>(&output[0]), cSize, NULL, NULL);
and this snippet should do conversion from single-byte std::string to LPWSTR
并且此代码段应该从单字节 std::string 转换为 LPWSTR
##代码##