德语变音符号作为命令行参数的编码错误

最后发布: 2013-02-10 19:17:13


问题

我的QTCreator运行x64 ArchLinux时遇到严重问题。 包含德语变音符号的命令行参数无效。 我想将它们转换为std :: string,这应该是可能的,至少这是我能读到的所有内容。

std::string arg(argv[1]);
// do something with arg

如果我使用调试器查看变量,它将显示一个有点转义的字符串。 例如,ä变为“ = \\”。 但是,如果我

std::cout << arg << std::endl;

该变量在我的控制台(urxvt)上完全可以。

我检查了QtCreator的编辑器设置(以前从未接触过),它说它使用UTF-8。 在将一些变音符号添加到注释中并执行后,我将源文件转换为UTF-8

% iconv -f ascii -t utf-8 main.cpp > _main.cpp
% mv _main.cpp main.cpp
# qtcreator recognized the change and ask me to reload the file, what I did

% file -bi main.cpp
# then results text/x-c; charset=utf-8, was text/x-c; charset=us-ascii before

没事。 我什至无法定义包含变音符号的std :: string:

std::string s("Mäx");
// the GDB debugger show 's' as: M=\x

然后,我从.pro文件中定义了UNICODE

DEFINES += UNICODE
# also without success

更令人迷惑的是,以下内容会产生不同的效果:

std::vector< std::string > list(argv, argv + argc);
# the debugger shows 2 elements (which is correct)
# but the element at index 1 looks like this: "Mäx"

我完全无助。 也许有人可以帮忙。 谢谢

@Olaf:

// lacks sanity checks but good enough for testing
std::wstring Encoding::char2Wide(const char *chars) {
    setlocale(LC_ALL, "");

    // get the length of the string to convert
    int len = mbstowcs(NULL, chars, 0) + 1;

    wchar_t* result = new wchar_t[len];
    len = mbstowcs(result, chars, len);

    std::wstring s(result);
    return s;
}

2013年2月11日

为了澄清一点,此图显示了std :: string的问题 std :: string的问题

控制台上的输出不是问题。 很好 这是我的语言环境设置

% locale
LANG=de_DE.UTF-8
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY="de_DE.UTF-8"
LC_MESSAGES="de_DE.UTF-8"
LC_PAPER="de_DE.UTF-8"
LC_NAME="de_DE.UTF-8"
LC_ADDRESS="de_DE.UTF-8"
LC_TELEPHONE="de_DE.UTF-8"
LC_MEASUREMENT="de_DE.UTF-8"
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

哈哈:

if ( s == "Mäx" ) std::cout << "Yeahhh" << endl;
-> Yeahhh (what the fxxx!)

也许这只是一个qtcreator问题。 我今天在Visual Studio中尝试了这个简单的例子,一切都按预期进行。 而且,它也可以按我期望的在Linux上使用Eclipse CDT的方式工作。 GDB显示正确的值。 我认为,我将提交一个错误。

更新

请在这里https://stackoverflow.com/a/14801772/76591获得正确答案。

c++ encoding stl qt-creator
回答

这一切都取决于qtcreator,urxvt,gdb等各种程序中使用的编码。

ascii转换为utf-8是没有意义的,因为每个仅ascii的文件已经经过utf-8编码。 前127个utf-8字符与127个us-ascii字符相同。

当我看std::string s("Mäx"); 在gdb中,我看到了

(gdb)ps
$ 1 = {静态npos = <优化输出>,
_M_dataplus = {<std :: allocator <char >> = {<__ gnu_cxx :: new_allocator <char >> = {<无数据字段>},<无数据字段>},_M_p = 0x602028“Mäx”}}

最后一个例子

#但索引1处的元素看起来像这样:“MÃx”

显示输出使用的是iso-8859-1 ,因为utf-8中的ä是两个字节的字符303 244八进制。 您可以分别使用man iso-8859-1进行验证。

因此,如果您在各种程序中看到不同的输出,则意味着它们使用不同的编码。

您涉及到两个程序urxvt和qtcreator。

根据此消息QtCreator和UTF-8 ,对于qtcreator,必须在项目的设置中设置编码。

对于urxvt,环境似乎是负责任的。 我已经设置了LANG=de_DE.UTF-8 ,它对于UTF-8字符串可以正常工作。 但是,如果我使用urxvt

LANG = de_DE urxvt

它在输出中将UTF-8字符串MäxMäx ,或在gdb中显示为"M\\303\\244x

当您使用urxvt启动时,您可以测试不同的行为

LANG=en_US.UTF-8 urxvt

要么

LANG=en_US urxvt

并比较各自的输出。

更新

您可以通过右键单击argv[1] ->“更改显示格式”->“ UTF-8字符串”来更改纯C字符串的显示。

对于std::string显示, M=\\x来自调试助手。 我在“工具”->“选项”->“调试器”->“调试助手”下禁用了调试助手。 然后,您可以看到std::string的各个成员,并更改_M_p以显示UTF-8字符串。


回答

只需使用wchar_t **作为main的第二个参数。