【问题标题】:converting narrow string to wide string将窄字符串转换为宽字符串
【发布时间】:2011-10-05 05:08:58
【问题描述】:

如何将窄的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字符串?

【问题讨论】:

  • 源代码是 UTF-8 编码的,还是 ASCII 码?

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


【解决方案1】:

如果源是 ASCII 编码的,你可以这样做:

wstring printerName;
printerName.assign( myName.begin(), myName.end() );

【讨论】:

  • 迄今为止最简单的方法。我很惊讶这没有更多的赞成票。
  • “我很惊讶这没有更多的赞成票。” 我猜是因为它在(也许)最常见的情况下失败了,即如果myName 是 UTF -8.
【解决方案2】:

你应该这样做:

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;
}

【讨论】:

  • 它通过使用 MultiByteToWideChar Win32 API 调用将窄 std::string(此处为 UTF-8)转换为 std::wstring。
  • 挑选 nits:最好传递对输出字符串的引用。这样你就不会依赖编译器来优化返回时的副本,并且如果有人使用该例程来转换书本长度的手稿,也不会出现堆栈溢出。
  • 生产质量代码也应该处理错误情况(例如抛出异常)。 This MSDN Magazine article,我在此处的答案中提供的链接,更详细地描述了该过程。
【解决方案3】:

我在谷歌搜索问题时发现了this。我已经粘贴了代码以供参考。这篇文章的作者是 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());

【讨论】:

  • @grassPro: L 仅适用于像L"Hello"; 这样的常量字符串。第二个错误是不言自明的,c_str() 返回 const wchar_t*,您无法将其转换为 wchar_t*
【解决方案4】:

ATL(Visual Studio 的非速成版)有几个有用的类类型,可以简单地转换字符串。如果您不需要保留字符串,则可以直接使用构造函数。

#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

【讨论】:

    【解决方案5】:

    这里有两个可以使用的函数: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

    【讨论】:

      【解决方案6】:

      Windows API 提供了执行此操作的例程:WideCharToMultiByte() 和 MultiByteToWideChar()。但是,它们使用起来很痛苦。每次转换都需要对例程进行两次调用,并且您必须注意分配/释放内存并确保字符串正确终止。你需要一个包装器!

      我的博客上有一个方便的 C++ 包装器,here,欢迎您使用。

      【讨论】:

        【解决方案7】:

        这个帖子最初的问题是:“如何将窄字符串转换为宽字符串?”

        但是,从问题中给出的示例代码来看,似乎不需要转换。相反,由于较新的编译器弃用了过去可以的东西,因此存在编译器错误。以下是我认为正在发生的事情:

            // 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 将大多数内容与字符串和宽字符串进行转换。

        【讨论】:

          【解决方案8】:

          This article 发表在 MSDN 杂志 2016 年 9 月号上,详细讨论了使用 Win32 API 进行的转换。

          请注意,使用MultiByteToWideChar()much faster,而不是在 Windows 上使用 std:: 东西。

          【讨论】:

            【解决方案9】:

            使用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);
            猜你喜欢
            • 2018-09-15
            • 1970-01-01
            • 2017-04-16
            • 1970-01-01
            • 2019-10-10
            • 2019-01-05
            • 2011-10-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多