LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: gulfstream

wcout没法显示中文

[复制链接]
发表于 2005-12-29 10:46:18 | 显示全部楼层
我晕。。。。。。。。,无语。
3.x系列和4.x系列差别那么大。都超过最新的ICC9.0了。
GCC太强大了,以前只有微软的编译器有这功能。我落伍了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-12-29 10:46:26 | 显示全部楼层
我用的gcc 4.0.3
debian testing
回复 支持 反对

使用道具 举报

发表于 2005-12-29 11:09:21 | 显示全部楼层
Post by gulfstream
新发现现象,
int main()
{
        setlocale(LC_ALL, "zh_CN.UTF-8");
        wchar_t* ws = L"a测试b测试c";
        std::wcout << ws << std::endl;
}
可以正常显示,但是
int main()
{
        setlocale(LC_ALL, "zh_CN.UTF-8");
        wchar_t* ws = L"a测试b测试c";
        std::wcout << ws << std::endl;

        char * c = "c测试b测试a";
        std::cout<<c<<std::endl;
}
只能输出:
a测试b测试c

如果:
int main()
{
        char * c = "c测试b测试a";
        std::cout<<c<<std::endl;

        setlocale(LC_ALL, "zh_CN.UTF-8");
        wchar_t* ws = L"a测试b测试c";
        std::wcout << ws << std::endl;
}
则输出:
c测试b测试a
aK bK c

在C++中,一个编译单元只能使用一个locale,中途不能更改。而且不能混用wcout和cout。所以你这两个程序的输出与预想不同是必然。
Post by realtang
但我以前看到的一些参考说因为标准C++对国际化支持的不好,所以wcout和wcin并没有实现。
不知道现在的情况是否有了改善了。

不觉的这句话自相矛盾吗?标准C++中直接定义了wchar_t类型,就是为了支持宽字符,从而提供对非英语语言的支持,还提供了wstring,wcout,wcin等。既然都定义了,为什么还说没有实现?只能说是编译器老旧而没有实现标准,而不是标准没有实现。
回复 支持 反对

使用道具 举报

发表于 2005-12-29 11:22:58 | 显示全部楼层
应该是以前老版本的GCC的C++标准库不能支持这些w开头的这些功能。
到了今天,应该是都能用了。开发人员之福啊。
回复 支持 反对

使用道具 举报

发表于 2005-12-29 17:19:57 | 显示全部楼层
#include <iostream>

int main()
{
        wchar_t* ws = L"a测试b测试c";
        std::wcout << ws << std::endl;
        int * p = (int *)ws;
        while (*p)
        {
          std::wcout << std::hex << *p++ << L'\n';
        }
}

[matt@localhost tmp]$ ./a.out
a??b??c
61
6d4b
8bd5
62
6d4b
8bd5
63

[matt@localhost tmp]$ locale
LANG=zh_CN.UTF-8
....

[matt@localhost tmp]$ g++ -v
使用内建 specs。
目标:i386-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --host=i386-redhat-linux
线程模型:posix
gcc 版本 4.0.2 20051125 (Red Hat 4.0.2-8)


就以上结果来看, L前缀是有用的,得到的是UNICODE字符序列(编译器将源代码中的UTF-8字符序列转换为了UCS2序列)
但是终端需要的UTF-8序列,所以虚拟终端上似乎无法正确显示中文字符。

我并不认为wcout输出时会自动将UNICODE转换为UTF-8。
而且显示中文的话(MultiByte编码),用std::cout等等就够了。
td::wcout等(WCS编码),应该在程序内部使用的(而不是在IO部分)。

这个论坛上有些讨论:
http://groups.google.com/groups?q=unicode+std%3A%3Astring

最后, 我想说
manphiz的代码能成功让我不得解呀。
回复 支持 反对

使用道具 举报

发表于 2005-12-29 17:27:32 | 显示全部楼层
这位兄弟,鄙人也是南航毕业的唉。
回复 支持 反对

使用道具 举报

发表于 2005-12-30 10:46:32 | 显示全部楼层
manphiz,我执行你的那段代码怎么报错:
$ g++ -o test test.cc
test.cc: In function ‘int main()’:
test.cc:6: 错误:converting to execution character set: 无效或不完整的多字节字符或宽字符
$

这是怎么会事?

我的系统是FC4,gcc4.02
回复 支持 反对

使用道具 举报

发表于 2005-12-30 18:06:21 | 显示全部楼层
To MatthewGong, jsean:
我也深感困惑,难道FC4的gcc都和别人不一样?我是Debian sid gcc 4.0.3 prerelease
再次帖一下我的情况:

  1. $ cat test.cc
  2. #include <iostream>

  3. int main()
  4. {
  5.                 setlocale(LC_ALL, "zh_CN.UTF-8");
  6.                 wchar_t* ws = L"a测试b测试c";
  7.                 std::wcout << ws << std::endl;
  8. }

  9. $ g++ -Wall -o test test.cc
  10. $ ./test
  11. a测试b测试c
  12. $

复制代码

不行的话把setlocale加上std::试试
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-12-30 21:26:15 | 显示全部楼层
改成setlocale(LC_ALL, "")试试

Post by jsean
manphiz,我执行你的那段代码怎么报错:
$ g++ -o test test.cc
test.cc: In function ‘int main()’:
test.cc:6: 错误:converting to execution character set: 无效或不完整的多字节字符或宽字符
$

这是怎么会事?

我的系统是FC4,gcc4.02
回复 支持 反对

使用道具 举报

发表于 2005-12-31 13:42:33 | 显示全部楼层
to gulfstream and manphiz:

都不行,这是为啥呀?
直接用如下代码没有问题:
    char* c = "c测试b测试a";
    std::cout<<c<<std::endl;
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表