项目的一部分包括类似于滚动“股票行情自动收录器”的内容,其中较大的字符串“滚动”固定宽度的输出字符串。
在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字符串)
在本机支持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来解决此问题。
[针对basic plane的多次警告之后,我基于引用wchar
中的this post的注释实施了一个解决方案。这种方法可能会有漏洞,但是到目前为止,在使用英语/拉丁语和日语输入进行测试时,对我来说仍然有效。
((我相信下面的代码仅适用于UTF-8,不确定其他传统编码,例如EUC-JP,SHIFT_JIS等)
请注意,rustyx标识存在的代码点数量,并且与屏幕宽度不同,因为可能存在不同的宽度(或零宽度!)代码点。
symbolLength()