来自字符串文字的 Unicode 与来自文件的 Unicode 会产生奇怪的行为

问题描述 投票:0回答:1

我一直在努力解决 C++ 中的 unicode 支持,并且出现了奇怪的行为。如果我从文件加载一行 unicode 文本,我可以将其存储在常规字符串中并将其输出到 stdout,而不会出现问题。但是,如果我使用具有完全相同字符的 unicode 字符串文字,我必须将其存储在 wstring 中,并且无法正确输出。为什么?

为什么可以在字符串中获取unicode而不需要wstring?为什么cout正确而wstring却无法wcout?

#include <fstream>
#include <iostream>
#include <string>

using namespace std;

int main(int argc,
         char* argv[])
{
    ifstream infile("unicode.txt");
    string strFromFile;
    getline(infile, strFromFile);
    infile.close();
    cout << "From file: " << strFromFile << endl;

    wstring strLiteral = L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ";
    wcout << "From literal: " << strLiteral << endl;

    return 0;
}

输出:

From file: ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
From literal: �
�"&*46A�JL��V^fj�t�N��
                      �!'157BqKM��W_gk�u�O�

我用以下内容编译了这个示例:

g++ main.cpp -Wall

我的编译器是:

g++ (Ubuntu 13.2.0-4ubuntu3) 13.2.0
c++ linux unicode
1个回答
0
投票

编码。您的文件很可能采用 UTF-8 格式,它以不同长度的字节序列对 Unicode 进行编码。打印您读取的字符串长度,并与显示的字符数进行比较。

或者做一个

hexdump -C unicode.txt
,然后观察右边的字符现在......垃圾。

不过,相比之下,

L""
字符串就复杂了。在我的系统上观察这些测试:

#include <iostream>
#include <string>

int main()
{
    std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp;  ./a.out
????????????M??????????CH???????????????????????n?ch??

与您的不同,但不是我们想要的。我们来做点别的吧:

#include <iostream>
#include <string>
#include <locale.h>

int main()
{
    setlocale(LC_ALL, "");
    std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp;  ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ

好多了。这是因为我们将语言环境设置为您首选的语言环境,而不是

"C"
语言环境,后者似乎讨厌 unicode。

但是,我们总是可以这样做:

#include <iostream>
#include <string>

int main()
{
    std::cout << "ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}
stieber@gatekeeper:~ $ g++ Test.cpp;  ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ

因为我们只是绕过区域设置并使用 UTF-8。

但是,请注意:

#include <iostream>
#include <string>
#include <locale.h>

int main()
{
    setlocale(LC_ALL, "");
    std::cout << "ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
    std::wcout << L"ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ\n";
}

这不起作用:

stieber@gatekeeper:~ $ g++ Test.cpp;  ./a.out
ĀƁĊĐĒƑĢĦĪĴĶŁΜŊŌƤǬŖŞŦŪƲŴΧɎƵāƂċđēƒġħıĵķłɱŋōƥǭŗşŧūνŵχɏƶ
▒
▒"&*46A▒JL▒▒V^fj▒t▒N▒▒
                      ▒!'157BqKM▒▒W_gk▒u▒O▒

我们先得到正确的字符串,然后得到乱码字符串。不要混合

std::cout
std::wcout
——我不完全确定这是为什么,或者我是否可以重置任何负责的东西,但目前看来这是一个坏主意。

© www.soinside.com 2019 - 2024. All rights reserved.