将窄字符串转换为宽字符串

10

如何将窄 string 转换为宽 string

我尝试了以下方法:

string myName;
getline( cin , myName );
wstring printerName( L(myName) );  // error C3861: 'L': identifier not found
wchar_t* WprinterName = printerName.c_str(); // error C2440: 'initializing' : cannot convert from 'const wchar_t *' to 'wchar_t *'

但是我得到了如上所列的错误。

为什么会出现这些错误?我该如何修复它们?

是否有其他直接将narrow字符串转换为wide字符串的方法?


2
源代码是UTF-8编码还是ASCII? - Blazes
9个回答

11
你应该这样做:
inline std::wstring convert( const std::string& as )
{
            // deal with trivial case of empty string
    if( as.empty() )    return std::wstring();

            // determine required length of new string
    size_t reqLength = ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), 0, 0 );

            // construct new string of required length
    std::wstring ret( reqLength, L'\0' );

            // convert old string to new string
    ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), &ret[0], (int)ret.length() );

            // return new string ( compiler should optimize this away )
    return ret;
}

这个代码期望将std::string作为UTF-8(CP_UTF8)进行处理,如果你使用了其他编码,请替换代码页。

另一种方式是:

inline std::wstring convert( const std::string& as )
{
    wchar_t* buf = new wchar_t[as.size() * 2 + 2];
    swprintf( buf, L"%S", as.c_str() );
    std::wstring rval = buf;
    delete[] buf;
    return rval;
}

1
它通过使用MultiByteToWideChar Win32 API调用,将一个窄的std::string(这里是UTF-8)转换为std::wstring。 - Christopher
1
挑刺一下:最好传递一个输出字符串的引用。这样,您就不会依赖编译器来优化返回时的复制,并且如果有人使用该例程将书长手稿转换,也不会出现堆栈溢出的情况。 - ravenspoint
生产质量的代码也应处理错误情况(例如,抛出异常)。我在这里提供的答案中提供了一个链接到此 MSDN Magazine 文章,其中详细描述了该过程。 - Mr.C64

11
如果源代码是ASCII编码的,你可以直接这样做:
wstring printerName;
printerName.assign( myName.begin(), myName.end() );

1
到目前为止,这是最简单的方法。我很惊讶为什么没有更多的赞。 - Bronco
2
“我很惊讶这个问题没有更多的赞。” 我猜是因为它在(也许)最常见的情况下失败了,即如果 myName 是 UTF-8。 - Sz.

4

ATL(Visual Studio的非Express版本)有一些有用的类类型,可以直接转换字符串。如果您不需要保留该字符串,则可以直接使用构造函数。

#include <atlbase.h>

std::wstring wideString(L"My wide string");
std::string narrowString("My not-so-wide string");

ATL::CW2A narrow(wideString.c_str()); // narrow is a narrow string
ATL::CA2W wide(asciiString.c_str()); // wide is a wide string

3
我在谷歌上搜索该问题时找到了这篇文章。我已经粘贴了代码以供参考。本文作者是Paul McKenzie。
std::string str = "Hello";
std::wstring str2(str.length(), L' '); // Make room for characters

// Copy string to wstring.
std::copy(str.begin(), str.end(), str2.begin());

3
L 只能用于常量字符串,比如 L"Hello";。第二个错误很明显,因为 c_str() 返回的是 const wchar_t* 类型,不能转换成 wchar_t* - Naveen

3
以下是两个可用的函数:mbstowcs_s和wcstombs_s。
mbstowcs_s:将一系列多字节字符转换为相应的宽字符序列。 wcstombs_s:将一系列宽字符转换为相应的多字节字符序列。
errno_t wcstombs_s(
   size_t *pReturnValue,
   char *mbstr,
   size_t sizeInBytes,
   const wchar_t *wcstr,
   size_t count 
);

errno_t mbstowcs_s(
   size_t *pReturnValue,
   wchar_t *wcstr,
   size_t sizeInWords,
   const char *mbstr,
   size_t count 

);

请参考http://msdn.microsoft.com/en-us/library/eyktyxsx.aspxhttp://msdn.microsoft.com/en-us/library/s7wzt4be.aspx


2
Windows API提供了执行此操作的例程:WideCharToMultiByte()和MultiByteToWideChar()。但是,它们很难使用。每次转换都需要两个调用例程,并且您必须负责分配/释放内存并确保字符串正确地终止。您需要一个包装器!
我在我的博客这里上提供了一个方便的C++包装器,欢迎您使用。

1
这个帖子最初的问题是:“如何将窄字符串转换为宽字符串?”
然而,从问题中给出的示例代码来看,似乎没有必要进行转换。相反,由于较新的编译器不再支持曾经可以使用的某些内容,所以会出现编译器错误。以下是我认为正在发生的事情:
    // wchar_t* wstr = L"A wide string";     // Error: cannot convert from 'const wchar_t *' to 'wchar_t *'

wchar_t const* wstr = L"A wide string";             // okay
const wchar_t* wstr_equivalent = L"A wide string";  // also okay

c_str()似乎与字面值被视为相同,并且被认为是一个常量(const)。你可以使用强制类型转换。但最好的方法是添加const。

我见过的将宽字符串和窄字符串之间转换的最佳答案是使用std::wstringstream。这是C++ Convert string (or char*) to wstring (or wchar_t*)给出的答案之一。

您可以使用stringstream和wstringstream将大多数内容转换为字符串和宽字符串。


0
使用 mbtowc():
string myName;
wchar_t wstr[BUFFER_SIZE];

getline( cin , myName );
mbtowc(wstr, myName, BUFFER_SIZE);

我正在调用mbtowc(),但是得到的是垃圾数据,但MultiByteToWideChar却正常。有什么想法吗? 错误示例:mbtowc(wczBuf, szBuf, strlen(szBuf)); 正确示例:MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, wczBuf, 4096); - Swiss Frank

0

本文发表于2016年9月的MSDN杂志,详细讨论了使用Win32 API进行转换。

请注意,在Windows上使用MultiByteToWideChar()比使用std:: stuff要快得多


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接