2011-09-21 67 views
7

我试图打印出wchar_t *字符串。 代码低于:char vs wchar_t

#include <stdio.h> 
#include <string.h> 
#include <wchar.h> 

char *ascii_ = "中日友好"; //line-1 
wchar_t *wchar_ = L"中日友好"; //line-2 

int main() 
{ 
    printf("ascii_: %s\n", ascii_); //line-3 
    wprintf(L"wchar_: %s\n", wchar_); //line-4 
    return 0; 
} 

//Output 
ascii_: 中日友好 

问:

  1. 显然我不应该分配CJK字符为char *指针线-1,但我只是做了,而且线路输出-3是正确的,那么为什么?第3行中的printf()怎么能给我非ascii字符?它以某种方式知道编码吗?

  2. 我假设第2行和第4行的代码是正确的,但为什么我没有得到任何第4行的输出?

+0

你使用什么编译器? GCC默认为大多数平台的Utf-8。似乎是一个编码问题给我。 – cyco130

+0

@ cyco130,是的,海湾合作委员会 – Alcott

回答

8

首先,在源代码中使用非ascii字符通常不是一个好主意。可能发生的情况是中文字符被编码为UTF-8,它与ascii一起使用。

现在,至于为什么wprintf()不工作。这与流方向有关。每个流只能设置为正常或宽。一旦设置,它就不能改变。它是第一次使用它。 (这是由于printf引起的ascii)。之后wprintf将不会工作,因为方向不正确。

换句话说,一旦你使用printf()你需要继续使用printf()。同样,如果您以wprintf()开头,则需要继续使用wprintf()

您不能混合printf()wprintf()。 (除了Windows)

编辑:

回答关于为什么wprintf线本身并不甚至工作的问题。这可能是因为代码正在编译,因此中日友好的UTF-8格式存储在wchar_中。但是,wchar_t需要4字节的unicode编码。 (在Windows中2个字节)

所以这是我能想到的两个选项:

  1. 不要打扰wchar_t,只是坚持多字节char秒。这是简单的方法,但如果用户的系统未设置为中文区域设置,则可能会中断。
  2. 使用wchar_t,但您需要使用unicode转义序列对中文字符进行编码。这显然会使其在源代码中无法读取,但它可以在任何可以打印汉字字体的机器上工作,而不管区域设置如何。
+0

如果使用unicode escape seq,我必须找出每个中文单词的seq,对吧?这将是相当多的工作要做,:P – Alcott

+1

正确。不过,我相信这是很常见的,你可以在网上找到一个工具,你可以复制和粘贴中文文本,它会给你unicode转义序列。为了保持代码的可读性,可以将转义序列旁边的实际中文文本保留为注释。 – Mysticial

+0

感谢Mysticial – Alcott

6

第1行不是ascii,它是编译器在编译时使用的多字节编码。在可能是UTF-8的现代系统上。 printf不知道编码。它只是发送字节到标准输出,只要编码匹配,一切都很好。

您应该意识到的一个问题是第3行和第4行一起调用未定义的行为。您不能在同一个FILEstdout)上混合基于字符和宽字符io。第一次操作后,FILE有一个“方向”(无论是字节还是宽),然后任何尝试执行相反方向的操作都会导致UB。

+0

我把注释掉了printf()行,我有一些输出,但不是中文字符。为什么? – Alcott

+0

本地的编码可能是错误的。 –

+0

区域设置的编码?如何解决它? – Alcott

1

您忽略了一个步骤,因此错误地思考。

您在磁盘上有一个包含字节的C文件。你有一个“ASCII”字符串和一个宽字符串。

ASCII字符串将字节与第1行中的字节完全相同并输出。 只要用户侧的编码与程序员侧的编码相同,此功能就可以工作。

宽字符串首先将给定的字节解码为unicode码点并存储在程序中 - 也许这在您身边出错。在输出时,它们根据用户侧的编码再次编码。这确保了这些字符按照它们的意图发出,而不是像它们输入的那样。

您的编译器会采用错误的编码,或者您的输出终端设置错误。