我有一个表示数字的任意 Unicode 字符串,例如“2”、“٢”(U+0662,阿拉伯印度数字二位)或“Ⅱ”(U+2161,罗马数字二)。我想将该字符串转换为一个 int。我不关心特定的语言环境(输入可能不在当前语言环境中);如果它是一个有效的数字,那么它应该被转换。
我尝试了 QString.toInt
和 QLocale.toInt
,但它们似乎无法完成工作。示例:
bool ok;
int n;
QString s = QChar(0x0662); // ARABIC-INDIC DIGIT TWO
n = s.toInt(&ok); // n == 0; ok == false
QLocale anyLocale(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
n = anyLocale.toInt(s, &ok); // n == 0; ok == false
QLocale cLocale = QLocale::C;
n = cLocale.toInt(s, &ok); // n == 0; ok == false
QLocale arabicLocale = QLocale::Arabic; // Specific locale. I don't want that.
n = arabicLocale.toInt(s, &ok); // n == 2; ok == true
我是否缺少某个功能?
我可以尝试所有语言环境:
QList<QLocale> allLocales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
for(int i = 0; i < allLocales.size(); i++)
{
n = allLocales[i].toInt(s, &ok);
if(ok)
break;
}
但这感觉有点老套。此外,它不适用于所有字符串(例如罗马数字,但这是一个可以接受的限制)。这样做是否有任何陷阱,例如不同语言环境中的冲突规则(参见土耳其语与非土耳其语字母大小写规则)?
最佳答案
我不知道有任何现成的包可以做到这一点(但是 也许 ICU 支持它),但如果你真的这样做并不难 想要。首先,您应该下载 UnicodeData.txt 文件 来自 http://www.unicode.org/Public/UNIDATA/UnicodeData.txt . 这是一个易于解析的 ASCII 文件;确切的语法是 在 http://www.unicode.org/reports/tr44/tr44-10.html 中描述, 但出于您的目的,您需要知道的是每一行 该文件由分号分隔的字段组成。首先 字段包含十六进制的字符代码,第三个字段 “一般类别”,如果第三个字段是“Nd”(数字, 十进制),第七个字段包含十进制值。
这个文件可以很容易地使用 Python 或其他一些工具来解析
脚本语言,构建映射表。你会想要一些
有点稀疏表示,因为有超过一百万
Unicode 字符,其中很少(几百个)是
十进制数字。下面的 Python 脚本会给你一个 C++
可用于初始化的表
std::map<int, int>
;.如果角色是
在映射中,映射的元素就是它的值。
这是否足够取决于您的应用程序。 它有几个弱点:
它需要额外的逻辑来识别两个连续的 数字在不同的字母表中。大概是一个序列
"1١"
应该被视为两个数字(1 和 1),而不是一个 (11). (因为所有十进制数字组都在 10 连续的代码,这将是相当容易的,一旦你知道了 数字,检查前面的数字字符是否在 同一套。)它会忽略非十进制数字,例如 ௰ 或 ൱(泰米尔十和 马来语一百)。没有那么多,而且他们是 也在 UnicodeData.txt 文件中,因此可能 手动找到它们并将它们添加到表中。我不知道 然而,我自己,当数字时它们如何与其他数字组合 已经组成。
如果您要转换数字,您可能需要担心 方向。我不确定这是如何处理的(但有 Unicode 站点上的文档);一般来说,文字会出现 按照其自然顺序。对于阿拉伯语及相关 语言,当以自然顺序阅读时,低阶 数字首先出现:类似于
"١٢"
(字面意思是"12"
, 但是因为书写是从右到左,所以数字会 出现在订单"21"
) 应该被解释为 12,而不是 21。除了我不确定是否有改变方向标记 存在与否。 (具体规则在 Unicode 站点上的文档;在 UnicodeData.txt 文件中, 第五个字段(索引 4)提供此信息。我 想想它是否不是"AN"
,你可以假设大端 欧洲使用的标准,但我不确定。)
为了展示这有多么简单,这里是 Python 脚本 解析数字值的 UnicodeData.txt 文件:
print('std::pair<int, int> initUnicodeMap[] = {')
for line in open("UnicodeData.txt"):
fields = line.split(';')
if fields[2] == 'Nd':
print(' {{{:d}, {:d}}},'.format(int(fields[0], 16), int(fields[7])))
print('};')
如果您正在使用 Unicode 进行任何工作,那么这个文件就是一座金矿 用于生成各种有用的表格。
关于c++ - 将任何 Unicode 字符串转换为 int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13780391/