【问题标题】:How to print wstring on Linux/OS X?如何在 Linux/OS X 上打印 wstring?
【发布时间】:2011-10-11 14:26:34
【问题描述】:

如何在控制台/屏幕上打印这样的字符串:€áa¢cée£?我试过这个:

#include <iostream>    
#include <string>
using namespace std;

wstring wStr = L"€áa¢cée£";

int main (void)
{
    wcout << wStr << " : " << wStr.length() << endl;
    return 0;
}

这不起作用。甚至令人困惑的是,如果我从字符串中删除,打印输出如下:?a?c?e? : 7 但字符串中有,在 字符之后不会打印任何内容。

如果我在 python 中编写相同的代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

wStr = u"€áa¢cée£"
print u"%s" % wStr

它在同一个控制台上正确打印出字符串。我在 C++ 中缺少什么(好吧,我只是一个菜鸟)?干杯!!


更新 1: 基于 n.m. 的建议
#include <iostream>
#include <string>
using namespace std;

string wStr = "€áa¢cée£";
char *pStr = 0;

int main (void)
{
    cout << wStr << " : " << wStr.length() << endl;

    pStr = &wStr[0];
    for (unsigned int i = 0; i < wStr.length(); i++) {
        cout << "char "<< i+1 << " # " << *pStr << " => " << pStr << endl;
        pStr++;
    }
    return 0;
}

首先,它将14 报告为字符串的长度:€áa¢cée£ : 14 是因为它计算每个字符2 个字节吗?

我得到的只是:

char 1 # ? => €áa¢cée£
char 2 # ? => ??áa¢cée£
char 3 # ? => ?áa¢cée£
char 4 # ? => áa¢cée£
char 5 # ? => ?a¢cée£
char 6 # a => a¢cée£
char 7 # ? => ¢cée£
char 8 # ? => ?cée£
char 9 # c => cée£
char 10 # ? => ée£
char 11 # ? => ?e£
char 12 # e => e£
char 13 # ? => £
char 14 # ? => ?

作为最后一个 cout 输出。所以,我相信实际问题仍然存在。干杯!!


更新2:基于n.m.的第二个建议

#include <iostream>
#include <string>

using namespace std;

wchar_t wStr[] = L"€áa¢cée£";
int iStr = sizeof(wStr) / sizeof(wStr[0]);        // length of the string
wchar_t *pStr = 0;

int main (void)
{
    setlocale (LC_ALL,"");
    wcout << wStr << " : " << iStr << endl;

    pStr = &wStr[0];
    for (int i = 0; i < iStr; i++) {
       wcout << *pStr << " => " <<  static_cast<void*>(pStr) << " => " << pStr << endl;
       pStr++;
    }
    return 0;
}

这就是我得到的结果:

€áa¢cée£ : 9
€ => 0x1000010e8 => €áa¢cée£
á => 0x1000010ec => áa¢cée£
a => 0x1000010f0 => a¢cée£
¢ => 0x1000010f4 => ¢cée£
c => 0x1000010f8 => cée£
é => 0x1000010fc => ée£
e => 0x100001100 => e£
£ => 0x100001104 => £
 => 0x100001108 => 

为什么报告为9 而不是8?或者这是我应该期待的?干杯!!

【问题讨论】:

  • 你的源代码文件的编码是什么? ASCII?
  • @selalerer: "源文件的编码" - 就像 python 中的# -*- coding: utf-8 -*-?我如何知道或在 C++ 中设置它?我只是使用 vim 来编写脚本。干杯!!
  • @Mac 每个源文件都只是一个文本文件。每个文本文件都有一些编码,它可以是基于 ASCII 表(其中每个字符是一个字节)或 UTF-8 或 UTF-16 等的一些东西......今天每个文本编辑器都支持保存文件的编码你选。如何在 vim 中做到这一点? stackoverflow.com/questions/778069/…
  • @selalerer:这就是它:uniTest.cpp: UTF-8 Unicode c program text。如果不是,我会感到惊讶。 vim 以完全相同的方式用于每件事,同时,例如python 可以,但 c++ 不行。你还缺少什么东西吗?干杯!

标签: c++ unicode wstring


【解决方案1】:

在字符串文字前删除L。使用std::string,而不是std::wstring

UPD:有更好(正确)的解决方案。保留 wchar_t、wstring 和 L,并在程序开头调用 setlocale(LC_ALL,"")

无论如何,您都应该在程序开始时调用setlocale(LC_ALL,"")。这指示您的程序使用环境的语言环境,而不是默认的“C”语言环境。您的环境有一个 UTF-8,所以一切都应该工作。

如果不调用setlocale(LC_ALL,""),程序会使用 UTF-8 序列而不“意识到”它们是 UTF-8。如果在终端上打印了正确的 UTF-8 序列,它将被解释为 UTF-8,一切看起来都很好。如果您使用stringchar,就会发生这种情况:gcc 使用UTF-8 作为字符串的默认编码,并且ostream 很高兴地打印它们而不应用任何转换。它认为它有一个 ASCII 字符序列。

但是当您使用wchar_t 时,一切都会中断:gcc 使用 UTF-32,不会应用正确的重新编码(因为语言环境是“C”)并且输出是垃圾。

当您调用 setlocale(LC_ALL,"") 时,程序知道它应该将 UTF-32 重新编码为 UTF-8,然后一切都恢复正常了。

这一切都假设我们只想使用 UTF-8。使用任意语言环境和编码超出了此答案的范围。

【讨论】:

  • 哇!!这真的有效。这让我又问了一个问题:wstring(因此,我认为也是wchar_t)实际上是为了什么?干杯!!
  • wchar_t 是一种“大到足以容纳系统字符集中的任何字符”的模糊类型,但这完全取决于您的平台如何处理。通常您必须使用mbstowcs/wcstombs 函数或%Ls 中的printf 等将它与环境接口。See here 用于我对这个主题的一点咆哮,或use C++0x 用于显式Unicode字符串。
  • @n.m.:嗯,我现在不太确定它是否真的有效:如果我尝试这样的事情:cout &lt;&lt; *pStr &lt;&lt; " =&gt; " &lt;&lt; pStr &lt;&lt; endl; - 它会在控制台上打印:? =&gt; €áa¢cée£pStr 是 char 类型的指针。我用新的修改后的脚本更新了我的原始帖子。干杯!!
  • @Kerrek SB:感谢您的链接。任何平台/操作系统都支持C++0x 吗?干杯!!
  • GCC 4.3 及更高版本以及 MSVS2010 支持 C++0x。不知道其他编译器...
猜你喜欢
  • 1970-01-01
  • 2020-10-14
  • 2010-09-11
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
相关资源
最近更新 更多