如何将 wchar_t\* 转换为 std::string?

新手上路,请多包涵

我将班级更改为使用 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>’

原文由 codefrog 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

您可以只使用 wstring 并将所有内容保留为 Unicode

原文由 Steve Townsend 发布,翻译遵循 CC BY-SA 2.5 许可协议

令人失望的是,这个老问题的答案都没有解决将宽字符串转换为 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";
}

这将按预期打印:

程序打印输出

解释

  • 7 似乎是缓冲区大小的最小安全值 BUFF_SIZE 。这包括 4 作为编码单个字符的最大 UTF-8 字节数; 2 表示可能的“移位序列”,1 表示尾随 '\0'
  • MB_CUR_MAX 是运行时 _变量_,所以 static_assert 在这里不可用
  • 每个宽字符都被翻译成它的 char 表示使用 std::wctomb
  • 仅当当前语言环境允许字符的多字节表示时,此转换才有意义
  • 为此,应用程序需要设置正确的语言环境。 en_US.utf8 似乎足够通用(在大多数机器上可用)。在 Linux 中,可以通过 locale -a 命令在控制台中查询可用的语言环境。

批评最受好评的答案

投票最多的答案,

 std::wstring ws( args.OptionArg() );
std::string test( ws.begin(), ws.end() );

仅当宽字符表示 ASCII 字符时才有效 - 但这些不是宽字符的设计目的。在此解决方案中,转换后的字符串包含每个源宽字符一个字符 ws.size() == test.size() 。因此,它会丢失原始 wstring 中的信息并生成无法解释为正确 UTF-8 序列的字符串。例如,在我的机器上,“ĄŚĆII”这个简单转换产生的字符串打印为“ZII”,即使它的大小是5(应该是8)。

原文由 zkoza 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题