【问题标题】:Convert const char* to wstring将 const char* 转换为 wstring
【发布时间】:2012-05-31 01:06:32
【问题描述】:

我正在开发基于锌的闪存应用程序的本机扩展,我需要将 const char* 转换为 wstring

这是我的代码:

mdmVariant_t* appendHexDataToFile(const zinc4CallInfo_t *pCallInfo, int paramCount, mdmVariant_t **params) {

    if(paramCount >= 2) {
        const char *file    = mdmVariantGetString(params[0]);
        const char *data    = mdmVariantGetString(params[1]);

        return mdmVariantNewInt(native.AppendHexDataToFile(file, data));
    }
    else {
        return mdmVariantNewBoolean(FALSE);
    }
}

但是native.AppendHexDataToFile() 需要两个wstring。 我对 C++ 不是很好,我认为所有这些不同的字符串类型完全令人困惑,而且我在网络中没有找到有用的东西。所以我问你们怎么做。

编辑:字符串是 UTF-8,我使用的是 OSX 和 Windows XP/Vista/7

【问题讨论】:

  • 在尝试处理字符和宽字符之前,您应该能够回答以下问题:您的字符串是如何编码的以及您打算进行什么转换?
  • 除了@ereOn,您还使用哪个平台?

标签: c++


【解决方案1】:

@anhoppe 对answer 的补充。下面是如何转换char*

#include <codecvt>
#include <locale> 

// ...

std::wstring stringToWstring(const char* utf8Bytes)
{
    //setup converter
    using convert_type = std::codecvt_utf8<typename std::wstring::value_type>;
    std::wstring_convert<convert_type, typename std::wstring::value_type> converter;

    //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
    return converter.from_bytes(utf8Bytes);
}

如果你也知道缓冲区的长度,下面是如何转换char*

#include <codecvt>

// ...

std::wstring stringToWstring(const char* utf8Bytes, const size_t numBytes)
{
    //setup converter
    using convert_type = std::codecvt_utf8<typename std::wstring::value_type>;
    std::wstring_convert<convert_type, typename std::wstring::value_type> converter;

    //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
    return converter.from_bytes(utf8Bytes, utf8Bytes + numBytes);
}

【讨论】:

  • std::wstring_convert 不包括 #include 至少在我的 Ubuntu 框中不可用
【解决方案2】:

AFAIK 这仅适用于 C++11 及更高版本:

#include <codecvt>

// ...

std::wstring stringToWstring(const std::string& t_str)
{
    //setup converter
    typedef std::codecvt_utf8<wchar_t> convert_type;
    std::wstring_convert<convert_type, wchar_t> converter;

    //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
    return converter.from_bytes(t_str);
}

Reference answer

【讨论】:

  • 在 C++17 中已弃用
  • @EnricoDetoma 到底弃用了什么?
  • std::wstring_convert 不包括 #include 至少在我的 Ubuntu 框中不可用
【解决方案3】:

我建议您尽可能使用 std::string 而不是 C 风格的字符串 (char*)。您可以从 const char* 创建 std::string 对象,只需将其传递给其构造函数即可。

拥有std::string 后,您可以创建简单的函数,将包含多字节UTF-8 字符的std::string 转换为包含UTF-16 编码点的std::wstring(来自std::string 的特殊字符的16 位表示) .

还有更多方法可以做到这一点,这里是使用MultiByteToWideChar function的方法:

std::wstring s2ws(const std::string& str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo( size_needed, 0 );
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

也请检查这些问题:
Mapping multibyte characters to their unicode point representation
Why use MultiByteToWideCharArray to convert std::string to std::wstring?

【讨论】:

  • 免责声明: MultiByteToWideChar 是一个仅限 Windows 的函数。 (OP 使用的是 Windows,但问题仅标记为 c++
  • 最好是跨平台解决方案。
  • @huahsin68 这仍然是 Windows 上最好的转换。正如 MS 所说的here“您的应用程序可以使用标准 C 运行时库函数在 Windows 代码页和 OEM 代码页之间进行转换。但是,使用这些函数存在数据丢失的风险,因为可以表示的字符每个代码页不完全匹配” 但是,我想知道在转换通过 WINAPI ...A() 函数(例如,从 GetWindowTextA)获得的字符串时是否应该使用 CP_ACP 代码页
【解决方案4】:

您可以将char字符串直接转换为wstring,代码如下:

char buf1[] = "12345678901234567890";
wstring ws(&buf1[0], &buf1[20]);

【讨论】:

    【解决方案5】:

    您需要一个可以编码/解码 UTF8 的库。不幸的是,这个功能不包含在 std c++ 库中。这是您可能会使用的一个库:http://utfcpp.sourceforge.net/

    这是一个使用它的示例:

    utf8::utf8to32(bytes.begin(), bytes.end(), std::back_inserter(wstr));
    

    【讨论】:

      【解决方案6】:

      在 OS X 上 wstring 使用 UTF-32 而不是 UTF-16。您可以像这样进行转换:

      #include <codecvt>
      #include <string>
      
      // make facets usable by giving them a public destructor
      template <class Facet>
      class usable_facet
          : public Facet
      {
      public:
          template <class ...Args>
              usable_facet(Args&& ...args)
                  : Facet(std::forward<Args>(args)...) {}
          ~usable_facet() {}
      };
      
      std::wstring s2ws(std::string const &s) {
          std::wstring_convert<
              usable_facet<std::codecvt<char32_t,char,std::mbstate_t>>
              ,char32_t> convert;
          std::u32string utf32 = convert.from_bytes(s);
          static_assert(sizeof(wchar_t)==sizeof(char32_t),"char32_t and wchar_t must have same size");
          return {begin(utf32),end(utf32)};
      }
      

      【讨论】:

        【解决方案7】:

        这是我找到的代码;

        std::wstring StringToWString(const std::string& s)
         {
         std::wstring temp(s.length(),L' ');
         std::copy(s.begin(), s.end(), temp.begin());
         return temp; 
         }
        

        这是原始论坛帖子,其中包含使用 Windows API 函数 MultiByteToWideChar 的可能的第二种解决方案:

        http://forums.codeguru.com/archive/index.php/t-193852.html

        【讨论】:

        • 如果传递给此函数的 std::string 包含需要转换为 UTF-16 编码的宽字符等价物的多字节字符怎么办?
        • 为什么不是' '?无论如何,它都会被复制功能擦除。为字符串腾出空间只是一个任意字符。
        • 那你知道这些字符会被重写,为什么还要把这些字符初始化为' '呢?
        • 因为复制功能不会创建缓冲区。需要先创建缓冲区,由构造函数完成。
        • 啊,抱歉,我现在才看到。我认为basic_string 也有只需要size_type count 的构造函数,就像std::vector 一样。
        猜你喜欢
        • 2011-06-05
        • 2018-01-14
        • 2014-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-10
        相关资源
        最近更新 更多