C Visual Studio 字符编码问题

新手上路,请多包涵

不能把我的头包裹在这个周围是一个真正的耻辱……

我正在使用法语 Windows (XP) 中的法语版本的 Visual Studio (2008)。发送到输出窗口的字符串中的法语口音已损坏。 输出窗口输入同上。典型的字符编码问题,我输入 ANSI,得到 UTF-8 作为回报,或者类似的东西。当向输出窗口显示“硬编码”字符串时,什么设置可以确保字符保留在 ANSI 中?

编辑:

例子:

 #include <iostream>

int main()
{
std:: cout << "àéêù" << std:: endl;

return 0;
}

将在输出中显示:

óúÛ¨

(此处编码为 HTML 以供您观赏)

我真的很想展示:

点点滴滴

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

阅读 590
2 个回答

在我进一步讨论之前,我应该提到你所做的不符合 c/c++ 标准。 规范 在 2.2 中说明了哪些字符集在源代码中是有效的。里面的内容不多,所有使用的字符都是ascii。所以……下面的一切都是关于一个特定的实现(碰巧是美国语言环境机器上的 VC2008)。

首先,您的 cout 行上有 4 个字符,输出上有 4 个字形。所以问题不是 UTF8 编码之一,因为它将多个源字符组合成更少的字形。

从您的源字符串到控制台上的显示,所有这些都起作用:

  1. 您的源文件采用什么编码(即编译器将如何看到您的 C++ 文件)
  2. 你的编译器对字符串文字做了什么,它理解什么源编码
  3. 您的 << 如何解释您传入的编码字符串
  4. 控制台期望什么编码
  5. 控制台如何将该输出转换为字体字形。

现在…

1和2是相当容易的。看起来编译器猜测源文件的格式,并将其解码为其内部表示。无论源编码是什么,它都会在当前代码页中生成字符串文字对应的数据块。我没有找到明确的细节/控制。

3更容易。除了控制代码, << 只是将数据向下传递给 char *。

4 由 SetConsoleOutputCP 控制。它应该默认为您的默认系统代码页。您还可以通过 GetConsoleOutputCP 您拥有哪一个(输入的控制方式不同,通过 SetConsoleCP

5是一个有趣的。我用 CP1252(西欧,windows)敲了敲头,想弄清楚为什么我不能让 é 正确显示。事实证明,我的系统字体没有该字符的字形,并且有用地使用了我的标准代码页的字形(大写 Theta,如果我不调用 SetConsoleOutputCP,我会得到相同的字形)。为了解决这个问题,我不得不将我在控制台上使用的字体更改为 Lucida Console(一种真正的字体)。

我从中学到了一些有趣的东西:

  • 源的编码无关紧要,只要编译器能弄清楚(值得注意的是,将其更改为 UTF8 并不会更改生成的代码。我的“é”字符串仍然用 CP1252 编码为 233 0 )
  • VC 正在为我似乎无法控制的字符串文字选择一个代码页。
  • 控制控制台显示的内容比我预期的更痛苦

那么……这对你意味着什么?以下是一些建议:

  • 不要在字符串文字中使用非 ascii。使用 控制编码的资源。
  • 确保您知道您的控制台需要什么编码,并且您的字体具有代表您发送的字符的字形。
  • 如果您想弄清楚在您的情况下使用了什么编码,我建议将字符的实际值打印为整数。 char * a = "é"; std::cout << (unsigned int) (unsigned char) a[0] 对我来说确实显示了 233,这恰好是 CP1252 中的编码。

顺便说一句,如果你得到的是 “ÓÚÛ¨” 而不是你粘贴的,那么看起来你的 4 个字节在某处被解释为 CP850

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

我试过这段代码:

 #include <iostream>
#include <fstream>
#include <sstream>

int main()
{
    std::wstringstream wss;
    wss << L"àéêù";
    std::wstring s = wss.str();
    const wchar_t* p = s.c_str();
    std::wcout << ws.str() << std::endl;

    std::wofstream file("C:\\a.txt");
    file << p << endl;

    return 0;
}

调试器显示 wss、s 和 p 都具有预期值(即“àéêù”),输出文件也是如此。然而,控制台中出现的是óúÛ¨。

因此,问题出在 Visual Studio 控制台中,而不是 C++ 中。使用 Bahbar 的出色回答,我补充说:

     SetConsoleOutputCP(1252);

作为第一行,然后控制台输出按原样出现。

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

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