带有UTF-8字符串的C ++“股票行情收录器”

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

项目的一部分包括类似于滚动“股票行情自动收录器”的内容,其中较大的字符串“滚动”固定宽度的输出字符串。

在Linux上使用C ++ 11,在使用拉丁字符时,这个概念很清楚。像这样的东西:

std::string inputString, outputString;
for (int inIdx = 0; inIdx < inputString.size(); inIdx++)
{
    // shift output one character left
    for (int i = 0; i < mOutputTextWidth - 1; i++)
        outputString[i] = outputString[i+1];

    // Append character to end of output
    if (inIdx < inputString.size())
        outputString[mTextWidth] = inputString.at(inIdx);
    sleep(1);
}

您会得到类似的东西:

[           ]
[          H]
[         HE]
[        HEL]
[      HELLO]
[     HELLO ]
[    HELLO  ]
[   HELLO   ]

我需要针对UTF-8非拉丁字符执行此操作。根据我的阅读,这是一个复杂的主题。特别是std::string::at[]返回一个字符,该字符在长UTF-8字符上中断。

在C ++中,这样做的正确方法是什么?

例如日语

[              ]
[            こ]
[          こん]
[        こんば]
[      こんばん]
[    こんばんは]
[  こんばんは  ]
[ こんばんは   ]

((我知道字形宽度会随语言而变化,没关系。我只是想不出如何操作UTF-8字符串)

c++ utf-8 stdstring
2个回答
0
投票

在本机支持Unicode的系统上(包括Linux)1,您可以简单地使用标准的C++ multibyte support并使用wchar_t类型来一次处理一个Unicode代码点。

例如这样:

wchar_t

#include <algorithm> #include <clocale> #include <cstdlib> #include <iostream> #include <string> #include <vector> int main() { std::string inputUTF8 = "こんばんは!"; // assuming this source is stored in UTF-8 std::setlocale(LC_ALL, "en_US.utf8"); // tell mbstowcs use want UTF-8->wchar_t conversion std::wcout.imbue(std::locale("en_US.utf8")); // tell std::wcout we want wchar_t->UTF-8 output std::vector<wchar_t> buf(inputUTF8.size() + 1); // reserve space int len = (int)std::mbstowcs(buf.data(), inputUTF8.c_str(), buf.size()); // convert to wchar_t if (len == -1) { std::cerr << "Invalid UTF-8 input\n"; // mbstowcs can fail return 1; } std::wstring out; for (int i = 0; i < len * 2; i++) { out.assign(std::max(0, len - i), L' '); // fill with ideographic space (U+3000) before out.append(buf.data(), std::max(0, i - len), std::min(len, i) - std::max(0, i - len)); out.append(std::max(0, i - len), L' '); // fill with ideographic space after std::wcout << L"[" << out << L"]\n"; } }

Output

请注意,[      ] [     こ] [    こん] [   こんば] [  こんばん] [ こんばんは] [こんばんは!] [んばんは! ] [ばんは!  ] [んは!   ] [は!    ] [!     ] 和其他语言环境的内容不是线程安全的。

另一种可能性是使用类似mbstowcs的库。


1不幸的是,在iconv上,Unicode支持被削弱;它的Windows长16位,实际上代表UTF-16,因此该程序仅适用于wchar_t代码点(仍然包括典型的CJK符号,但不包括统一的Han或U + FFFF上方的其他符号) 。尽管仍然可以通过考虑UTF-16来解决此问题。


0
投票

[针对basic plane的多次警告之后,我基于引用wchar中的this post的注释实施了一个解决方案。这种方法可能会有漏洞,但是到目前为止,在使用英语/拉丁语和日语输入进行测试时,对我来说仍然有效。

((我相信下面的代码仅适用于UTF-8,不确定其他传统编码,例如EUC-JP,SHIFT_JIS等)

请注意,rustyx标识存在的代码点数量,并且与屏幕宽度不同,因为可能存在不同的宽度(或零宽度!)代码点。

symbolLength()
© www.soinside.com 2019 - 2024. All rights reserved.