我将班级更改为使用 std::string (基于我在这里得到的答案,但我有一个函数返回 wchar_t *。如何将其转换为 std::string?
我试过这个:
std::string test = args.OptionArg();
但它显示错误 C2440: 'initializing' : cannot convert from 'wchar_t *' to 'std::basic_string<_Elem,_Traits,_Ax>'
std::wstring ws( args.OptionArg() );
std::string test( ws.begin(), ws.end() );
您可以使用以下函数将宽字符字符串转换为 ASCII 字符串:
#include <locale>
#include <sstream>
#include <string>
std::string ToNarrow( const wchar_t *s, char dfault = '?',
const std::locale& loc = std::locale() )
{
std::ostringstream stm;
while( *s != L'\0' ) {
stm << std::use_facet< std::ctype<wchar_t> >( loc ).narrow( *s++, dfault );
}
return stm.str();
}
请注意,这只会用参数替换不存在等效 ASCII 字符的任何宽字符dfault
;它不会从 UTF-16 转换为 UTF-8。如果要转换为 UTF-8,请使用ICU等库。
这是一个老问题,但如果你不是真的在寻求转换,而是使用来自 Mircosoft 的 TCHAR 东西来构建 ASCII 和 Unicode,你可能记得 std::string 真的
typedef std::basic_string<char> string
所以我们可以定义我们自己的 typedef,比如说
#include <string>
namespace magic {
typedef std::basic_string<TCHAR> string;
}
然后你可以使用magic::string
with TCHAR
, LPCTSTR
, 等等
您可以使用wstring
并保留 Unicode 中的所有内容
只是为了好玩 :-):
const wchar_t* val = L"hello mfc";
std::string test((LPCTSTR)CString(val));
以下代码更简洁:
wchar_t wstr[500];
char string[500];
sprintf(string,"%ls",wstr);
令人失望的是,这个老问题的答案都没有解决将宽字符串转换为 UTF-8 字符串的问题,这在非英语环境中很重要。
这是一个有效的示例代码,可用作构建自定义转换器的提示。它基于cppreference.com 中示例代码的示例代码。
#include <iostream>
#include <clocale>
#include <string>
#include <cstdlib>
#include <array>
std::string convert(const std::wstring& wstr)
{
const int BUFF_SIZE = 7;
if (MB_CUR_MAX >= BUFF_SIZE) throw std::invalid_argument("BUFF_SIZE too small");
std::string result;
bool shifts = std::wctomb(nullptr, 0); // reset the conversion state
for (const wchar_t wc : wstr)
{
std::array<char, BUFF_SIZE> buffer;
const int ret = std::wctomb(buffer.data(), wc);
if (ret < 0) throw std::invalid_argument("inconvertible wide characters in the current locale");
buffer[ret] = '\0'; // make 'buffer' contain a C-style string
result = result + std::string(buffer.data());
}
return result;
}
int main()
{
auto loc = std::setlocale(LC_ALL, "en_US.utf8"); // UTF-8
if (loc == nullptr) throw std::logic_error("failed to set locale");
std::wstring wstr = L"aąß水-扫描-€\u00df\u6c34\U0001d10b";
std::cout << convert(wstr) << "\n";
}
这将按预期打印:
BUFF_SIZE
. 这包括 4 作为编码单个字符的最大 UTF-8 字节数;2 表示可能的“移位序列”,1 表示尾随'\0'
.MB_CUR_MAX
是一个运行时变量,所以static_assert
在这里不可用char
使用 std::wctomb
en_US.utf8
似乎足够通用(在大多数机器上可用)。locale -a
在 Linux 中,可以通过命令在控制台中查询可用的语言环境。投票最多的答案,
std::wstring ws( args.OptionArg() );
std::string test( ws.begin(), ws.end() );
仅当宽字符表示 ASCII 字符时才有效 - 但这些不是宽字符的设计目的。在此解决方案中,转换后的字符串包含每个源宽字符一个字符,ws.size() == test.size()
. 因此,它会丢失原始 wstring 中的信息并生成无法解释为正确 UTF-8 序列的字符串。例如,在我的机器上,“ĄŚĆII”这个简单转换产生的字符串打印为“ZII”,即使它的大小是5(应该是8)。