字符使用“为\ uXXXX”格式显示错误的字符

问题描述:

我使用开发的C++,窗口7字符使用“为 uXXXX”格式显示错误的字符

我试图使用打印出非ASCII字符定义:

#include <locale.h> 
#include <iostream> 
#include <cstdlib> 
#include <windows.h> 
#include <conio.h> 
#include <stdio.h> 

using namespace std; 

int main() 
{ 
    setlocale(LC_ALL,"en_US.UTF-8"); 
    char a='\u0041'; //Should display 'A' 
    cout<<a<<endl; 
    a='\u2639'; //Should display '☹' 
    cout<<a<<endl; 
    system("PAUSE"); 
} 

在这个例子中,大写字母A显示正确。使用wxDev,simply字符不会显示任何内容。使用Dev(我需要用于最终的程序),我会得到一个扩展的ascii字符(这是一个与∥类似的符号,但有多个符号,看起来像这样,我不知道它是哪一个)。

在Dev和wxDev中,☹都显示为?。

我在一些关于如何正确显示unicode字符的初步搜索之后添加了setlocale,但我还没有找到任何解决方案。

我不能使用不同的编译器或修改系统设置来使其工作。 (是的,这是一个学校项目,不是,项目不需要特殊字符;我只是想让它看起来更好)。如果修改这些设置无法正常工作,那也是非常有用的信息。

非常感谢您的帮助。

编辑:使用开发,不wxDev,

char a='\u0041'; //should be A 
cout<<a; 

我得到一个错误:\ u0041是不是有效的普遍性

如果我使用的wchar_t作为数据类型:

wchar_t a = '\u2639'; 
cout<<a<<endl; 

输出为39097.

+14

'所以char a ='\ u2639''是不可能做到你想要什么,因为'char'(定义)是一个字节,并且'\ u2639'不能放在一个字节中(至少当一个字节是八位时,因为它几乎总是)。对于替代品,您可以尝试使用谷歌搜索“宽字符”或“wchar”。 – ruakh 2013-03-21 22:01:51

通用字符名称(UCN)是一种将t o编译器中要表示的角色。只要您可以将基本源字符传送到编译器,那么每个编译器都会看到相同的UCN,因此会看到您表示的是相同的字符。

这是相对于在源字面上写字符:

char a = '☹'; 

由于编译器只需要支持基本源字符的编译器甚至可以是不能够处理该代码。它实际看到的取决于编译器使用的源编码。一个编译器可能会看到你想要的字符,而另一个编译器看到

char a = 'Â☐¹'; 

然而,仅仅是因为UCNs能够指定字符的编译器并不意味着:

  • 编译器的执行字符集包含字符或
  • 数据类型char可以表示字符值

在你的情况下,主要问题是执行字符集是没有字符'☹'的Windows代码页(可能是CP1252)之一。所以当编译器将字符'☹'转换成执行字符集时,转换会产生'?'而不是你想要的。

我的编译器设置执行字符不包括字符“☹”,但它发生,所以我的编译器说有一个多字节表示:

error: character too large for enclosing character literal type 
    char a = '☹'; 
      ^

要真正理解这个主题中,您需要了解编码,字符集,它们如何在翻译的C++阶段中发挥作用,以及它们如何与编译器处理字符和字符串文字有关。而且,语言环境真的与这些没有任何关系; locales处理运行时行为,而您的问题完全在于您的编译器编译时处理编码。


在使用UTF-8无处不在以下工作平台:

#include <iostream> 

int main() { 
    std::cout << "☹\n"; 
} 

注意上面使用字符串文字而不是字符文字,让角色可以扩大其多字节表示。

不幸的是Windows不支持Unicode这种方式。在Windows上它更复杂:

#include <Windows.h> 
#include <cwchar> 

int main() { 
    wchar_t const *a = L"\u2639\n"; 
    DWORD numOfCharsWritten; 
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), a, wcslen(a), &numOfCharsWritten, NULL); 
} 

不幸的是,即使上面的代码是不太可能显示你想要什么,因为在Windows控制台通常没有配置到能够显示Unicode字符“☹”。相反,您可能需要查看控制台(可能是CP437)使用的OEM编码,查找所需字符的编码,然后打印出该值。例如CP437具有“☺”字代替,你可以打印出这样的:

#include <iostream> 

int main() { 
    std::cout << "\x01\n"; // ☺ has the value 0x01 in CP 437 
} 
+0

如果你用'chcp 65001'运行控制台,并将字体改为比默认字体更古老的字体,不应该使用'std :: cout Esailija 2013-03-23 14:25:57

+0

虽然阻止编译器在源编码和其执行编码之间进行转换(通过将文件另存为无签名的UTF-8),但它会工作,但会打破宽字符文字。而且没有其他方法可以用VC++来实现。 – bames53 2013-03-24 04:30:32

+0

谢谢你的一个很好的解释!这也是可以理解的。我会看看我是否可以修复代码页,但如果不能,我至少明白为什么它现在不起作用。 – helloworld112358 2013-03-26 12:32:54