MPe*_*ier 15 c++ character-encoding visual-studio
无法绕过这一个是一个真正的耻辱源...
我在法语Windows(XP)中使用法语版的Visual Studio(2008).发送到输出窗口的字符串中的法语重音被破坏.从输出窗口输入Ditto .典型的字符编码问题,我输入ANSI,得到UTF-8作为回报,或者那样的东西.在向输出窗口显示"硬编码"字符串时,什么设置可以确保字符保留在ANSI中?
编辑:
例:
#include <iostream>
int main()
{
std:: cout << "àéêù" << std:: endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
将在输出中显示:
奥羽
(此处编码为HTML以供您观看乐趣)
我真的很想表明:
àéêù
Bah*_*bar 15
在进一步讨论之前,我应该提一下你所做的不是c/c ++兼容.该规范中2.2什么字符集的状态是在源代码中有效.它并不多,所有使用的字符都在ascii中.所以...下面的所有内容都是关于特定的实现(就像在美国语言环境机器上的VC2008).
首先,你的cout线上有4个字符,输出上有4个字形.所以问题不是UTF8编码,因为它会将多个源字符组合成较少的字形.
从您的源字符串到控制台上的显示,所有这些都起到了作用:
<<解释你传入的编码字符串现在...
1和2是相当容易的.看起来编译器猜测源文件的格式,并将其解码为内部表示.无论源编码是什么,它都会在当前代码页中生成字符串文字对应的数据块.我没有找到明确的细节/控制.
3甚至更容易.除了控制代码,<<只需将数据传递给char*.
4由...控制SetConsoleOutputCP.它应默认为您的默认系统代码页.你也可以找出你拥有的GetConsoleOutputCP那个(输入的控制方式不同,通过SetConsoleCP)
5是一个有趣的.我猛烈地想弄清楚为什么我不能使用CP1252(西欧,windows)来正确显示é.事实证明我的系统字体没有该字符的字形,并且有助于使用我的标准代码页的字形(资本Theta,如果我没有调用SetConsoleOutputCP,我会得到的字形).为了解决这个问题,我不得不将我在控制台上使用的字体更改为Lucida Console(一种真正的字体).
我学到了一些有趣的东西:
233 0)那么......这对你意味着什么?以下是一些建议:
char * a = "é"; std::cout << (unsigned int) (unsigned char) a[0]确实为我显示233,这恰好是CP1252中的编码.顺便说一句,如果你得到的是"ÓÚÛ"而不是你粘贴的东西,那么看起来你的4个字节被解释为CP850.
小智 6
试试这个:
#include <iostream>
#include <locale>
int main()
{
std::locale::global(std::locale(""));
std::cout << "àéêù" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因为我被要求做,所以我会做一些巫术。其他答案来自2009年,但本文仍然基于我在2018年所做的搜索。今天的情况大不相同。此外,即使在2009年,接受的答案还是不完整的。
每个编译器(包括Microsoft的Visual Studio 2008和更高版本,gcc,clang和icc)都将读取以BOM开头的UTF-8源文件,而不会出现问题,并且clang除了UTF-8之外不会读取任何内容,因此带有BOM的UTF-8是C和C ++源文件的最低公分母。
语言标准没有说明编译器需要支持哪些源字符集。某些实际的源文件甚至保存在与ASCII不兼容的字符集中。Microsoft Visual C ++在2008年支持带字节顺序标记的UTF-8源文件,以及两种形式的UTF-16。如果没有字节顺序标记,则将假定文件是在当前的8位代码页中编码的,该页始终是ASCII的超集。
在2012年,编译器向添加了一个/utf-8开关CL.EXE。今天,它还支持/source-charset和/execution-charset开关,以及/validate-charset检测您的文件是否实际上不是UTF-8。 MSDN上的此页面上有指向每个Visual C ++版本的Unicode支持文档的链接。
当前版本的C ++标准说,编译器必须同时具有确定字符常量(如)的数值'a'的执行字符集和确定宽字符常量(如)的值的执行宽字符集L'é'。
对于语言律师来说,标准中对如何编码这些要求几乎没有要求,但是Visual C和C ++设法打破了这些要求。它必须包含那些不能有负值100个字符,而数字的编码'0'通过'9'必须是连续的。不必使用大写字母或小写字母,因为它们不在某些旧的大型机上。(也就是说,'0'+9必须是相同的'9',但仍然有一个编译器在实际使用中,其今天的默认行为是'a'+9没有'j',但'«',这是合法的。)宽字符执行集必须包括基本执行集,并具有足够的位来容纳任何受支持语言环境的所有字符。每个主流编译器都至少支持一个Unicode语言环境,并且可以理解使用所指定的有效Unicode字符\Uxxxxxxxx,但是编译器却不能声称自己符合该标准。
Visual C和C ++违反语言标准的方式是制作它们的wchar_tUTF-16,当标准说wchar_t必须是固定宽度编码时,它们只能将某些字符表示为代理对。这是因为Microsoft wchar_t在1990年代定义为16位宽,然后Unicode委员会才发现16位宽对于整个世界来说是不够的,并且Microsoft不会破坏Windows API。它也支持标准char32_t类型。
这个问题引起的第三个问题是如何使编译器在内存中将字符串文字编码为UTF-8。从C ++ 11开始,您已经可以编写如下代码:
constexpr unsigned char hola_utf8[] = u8"¡Hola, mundo!";
Run Code Online (Sandbox Code Playgroud)
不管源字符集是UTF-8,UTF-16,Latin-1,CP1252还是IBM EBCDIC 1047(这都是一个愚蠢的理论示例,但是,为了向后兼容,IBM Z系列大型机编译器上的默认设置)。也就是说,等效于使用初始化数组{ 0xC2, 0xA1, 'H', /* ... , */ '!', 0 }。
如果在其中键入字符太不方便,或者想要区分表面上相同的字符(例如空格和不间断空格)或预先组合的字符,则还可以使用通用字符转义符:
constexpr unsigned char hola_utf8[] = u8"\u00a1Hola, mundo!";
Run Code Online (Sandbox Code Playgroud)
无论源字符集如何,以及将文字存储为UTF-8,UTF-16还是UCS-4,都可以使用它们。它们最初是在C99中添加的,但是Microsoft在Visual Studio 2015中支持它们。
编辑:据马修报道,u8"字符串在某些版本的MSVC中有错误,包括19.14。事实证明,即使您指定/utf-8或,文字非ASCII字符也是如此/source-charset:utf-8 /execution-charset:utf-8。上面的示例代码在19.22.27905中可以正常工作。
但是,还有另一种方法可以在Visual C或C ++ 2008中使用:八进制和十六进制转义码。您应该使用以下版本在该版本的编译器中对UTF-8文字进行编码:
const unsigned char hola_utf8[] = "\xC2\xA1Hello, world!";
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21697 次 |
| 最近记录: |