【问题标题】:Unexpected results with wchar_t and c_str string conversionwchar_t 和 c_str 字符串转换的意外结果
【发布时间】:2013-10-14 17:50:21
【问题描述】:

基于this answer 到一个相关问题,我尝试编写一个将标准字符串转换为宽字符串的方法,然后我可以将其转换为 wchar_t*。

为什么不是创建 wchar_t* 等价物的两种不同方法? (我已经展示了我的调试器给我的值)。

TEST_METHOD(TestingAssertsWithGetWideString)
{
   std::wstring wString1 = GetWideString("me");
   const wchar_t* wchar1 = wString1.c_str(); // wchar1 = "me"
   const wchar_t* wchar2 = GetWideString("me").c_str(); // wchar2 = "ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ@" (Why?!)
}

其中GetWideString定义如下:

inline const std::wstring GetWideString(const std::string &str)
{
   std::wstring wstr;
   wstr.assign(str.begin(), str.end());

   return wstr;
};

注意:以下也不起作用。

const wchar_t* wchar2 = GetWChar("me");

const wchar_t *GetWChar(const std::string &str)
{
   std::wstring wstr;
   wstr.assign(str.begin(), str.end());

   return wstr.c_str();
};

【问题讨论】:

  • // Why doesn't this work?! - 你有一个指向临时缓冲区的指针。

标签: c++ string type-conversion wstring string-conversion


【解决方案1】:

每次调用GetWideString() 时,都会创建一个新的std::wstring,它有一个新分配的内存缓冲区。您正在比较指向不同内存块的指针(假设 Assert::AreEqual() 只是比较 指针 本身,而不是所指向的内存块的 内容)。

更新const wchar_t* wchar2 = GetWideString("me").c_str(); 不起作用,因为GetWideString() 返回一个临时的std::wstring,它超出范围并在语句完成后立即被释放。因此,您正在获取一个指向临时内存块的指针,然后在该内存被释放时让该指针悬空,然后您才能将指针用于任何事情。

另外,const wchar_t* wchar2 = GetWChar("me"); 不应该编译。 GetWChar() 返回一个std::wstring,它没有实现到wchar_t* 的隐式转换。您必须使用c_str() 方法从std::wstring 获取wchar_t*

【讨论】:

  • 好点,但我已经编辑了我的问题以澄清我在寻找什么。
  • 感谢您的解释。我没有意识到返回的 std::wstring 超出了范围。 (PS 我已经修复了你说不应该编译的部分。那是一个错字)。
  • 我明白std::string 使用char 吗?作为一个试图学习新的做事方式的老程序员,我很难找到学习std:string 的理由。不要告诉我它不支持开箱即用的宽字符。
  • @JonathanWood std::string 使用 char,是的。 std::wstring 使用 wchar_t 代替。而在 C++11 中,现在还有使用 char16_tstd::u16string 和使用 char32_tstd::u32string
【解决方案2】:

因为两个指针不相等。 wchar_t * 不是 String,所以你会得到 generic AreEqual

【讨论】:

  • 好点,但我已经编辑了我的问题以澄清我在寻找什么。
【解决方案3】:

std::wstring 包含wchar_t 类型的宽字符。 std::string 包含 char 类型的字符。对于存储在std::string 中的特殊字符,正在使用多字节编码,即,某些字符由此类字符串中的 2 个字符表示。因此,在这些之间进行转换并不像调用简单的assign 那样容易。

要在“宽”字符串和多字节字符串之间进行转换,您可以使用以下帮助程序(仅限 Windows):

// multi byte to wide char:
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;
}

// wide char to multi byte:
std::string ws2s(const std::wstring& wstr)
{
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0); 
    std::string strTo(size_needed, 0);
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0); 
    return strTo;
}

【讨论】:

  • 假设没有任何特殊字符,我的简单分配将按预期工作是否正确?
猜你喜欢
  • 2021-12-27
  • 2018-04-29
  • 1970-01-01
  • 2012-10-18
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-02
相关资源
最近更新 更多