【问题标题】:C++ creating CString from std::string failsC++ 从 std::string 创建 CString 失败
【发布时间】:2019-01-25 18:03:19
【问题描述】:

在我基于 MFC 的应用程序中,此代码:

std::string stdString("MappingName");
std::cout << "as String: " << stdString << std::endl;
CString cString(stdString.c_str());
std::cout << "as CString: " << cString << std::endl;

产生这个输出:

as String: MappingName
as CString: 01DEA060

每次运行CString的值都不一样,但长度似乎是恒定的。其他一些结果是042219B0042C4378

我已经尝试了this thread 中讨论的所有变体,结果都是一样的。我还尝试将 Visual Studio 项目中的字符集从 Use Unicode Character Set 更改为 Use Multi-Byte Character Set,同样没有效果。

转换失败的原因可能是什么?

编辑: 更多测试表明std::string 的值似乎没有什么区别:

tmp as String: The quick brown fox jumps over the lazy dog
tmp as CString: 00EAAF88

我还将字符集设置为 Not Set,这也没有帮助。

【问题讨论】:

    标签: c++ visual-studio mfc c-strings stdstring


    【解决方案1】:

    问题是打印而不是转换。

    CString 可以隐式转换为TCHAR const*。在启用 unicode 构建时,这是wchar_t const*

    std::cout 对于&lt;&lt; 没有wchar_t const* 过载。它确实有 void const* 过载。

    void 指针重载以十六进制打印指针地址。

    打印前转换为CStringA

    std::cout << "as CString: " << static_cast<CStringA>(cString) << std::endl;
    

    或者使用wcout打印。

    【讨论】:

    • "Cast to CStringA" ... 或者直接创建一个CStringA 变量以避免强制转换。
    • 特别是,因为演员表调用了 有损 转换。从 ANSI 到 Unicode 再到 ANSI 的往返传输可能是安全的,但一般情况下并非如此。
    • @iinsp 但是,它是 cout 可以处理的最好的。
    • 想必cout只是作为一个例子。这不是真正的代码。
    • @iinsp 与 void const*char const* API 的其他接口,将 void 大小写解释为以十六进制解释为字符串值的指针地址,因此被 @ 的 wchar_t const* 转换运算符混淆我想 987654336@ 可能是真正的问题。但我对此表示怀疑。正如我所读到的,这个问题是关于微软隐式转换为宽字符的狭窄冲突以及 cout 流的许可接口导致令人困惑的结果行为。
    【解决方案2】:

    这个问题是两个方面的结合:

    • 字符串类型与显式编码 (std::string) 和通用文本映射(CStringCStringA/CStringW)的混合。
    • CString 通过conversion c'tors 在编码之间进行转换的能力。

    std::string 转换成CString 就好了,大概构造了一个CStringW 对象。由于std::ostream 没有operator&lt;&lt; 重载,它采用wchar_t const*(其中CStringW implicitly converts to),它只打印地址,匹配通用void const* 重载。

    这里的解决方案是从图片中取出通用文本映射,并构造一个匹配源编码的CString 特化(ANSI 代表std::string,即CStringA):

    std::string stdString("MappingName");
    std::cout << "as String: " << stdString << std::endl;
    CStringA cString(stdString.c_str());
    std::cout << "as CString: " << cString.GetString() << std::endl;
    

    要在构造CStrings 时获得有关隐式转换的通知,您可以#define _CSTRING_DISABLE_NARROW_WIDE_CONVERSION 处理器符号。如果您尝试调用任何转换 c'tors,这将反过来生成编译器错误。

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 2020-07-14
      • 2018-03-20
      • 2020-05-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2020-04-12
      • 2012-05-08
      相关资源
      最近更新 更多