1

「2」、「٢」(U+0662、ARABIC-INDIC DIGIT TWO)、「Ⅱ」(U+2161、ROMAN NUMERAL TWO)など、数値を表す任意の Unicode 文字列があります。その文字列を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;
}

しかし、それは少しハックな気がします。また、すべての文字列に対して機能するわけではありません (たとえば、ローマ数字ですが、許容できる制限です)。異なるロケールでルールが競合するなど、そのようにする際に落とし穴はありますか (トルコ語と非トルコ語の大文字と小文字のルールを参照)。

4

2 に答える 2

4

これを行うすぐに使用できるパッケージは知りませんが (ICU がサポートしている可能性があります)、本当にやりたい場合は難しくありません。最初に、 http://www.unicode.org/Public/UNIDATA/UnicodeData.txtから UnicodeData.txt ファイルをダウンロードする必要があります。これは解析しやすい ASCII ファイルです。正確な構文はhttp://www.unicode.org/reports/tr44/tr44-10.htmlで説明されていますが、目的のために知っておく必要があるのは、ファイルの各行がセミコロンで区切られたフィールドで構成されていることだけです。 . 最初のフィールドは 16 進数の文字コード、3 番目のフィールドは「一般カテゴリ」、3 番目のフィールドが「Nd」(数値、10 進数) の場合、7 番目のフィールドは 10 進数の値を含みます。

このファイルは、Python または他の多くのスクリプト言語を使用して簡単に解析し、マッピング テーブルを作成できます。100 万を超える Unicode 文字があり、そのうちのごくわずか (数百) が 10 進数であるため、ある種の疎な表現が必要になります。次の Python スクリプトは、; の初期化に使用できる C++ テーブルを提供し std::map<int, int>ます。文字がマップにある場合、マップされた要素はその値です。

これで十分かどうかは、アプリケーションによって異なります。いくつかの弱点があります。

  • 連続する 2 つの数字が異なるアルファベットにある場合を認識するために、追加のロジックが必要です。おそらく、数列"1١" は 1 つの数字 (11) ではなく、2 つの数字 (1 と 1) として扱われるべきです。(10 進数のすべてのセットは 10 個の連続するコードに含まれているため、数字がわかれば、前の数字の文字が同じセットに含まれているかどうかを確認するのはかなり簡単です。)

  • ௰ や ൱ (タミル語の 10 とマラヤ語の 100) などの 10 進数以外の数字は無視されます。それらの数はそれほど多くなく、UnicodeData.txt ファイルにも含まれているため、手動で見つけてテーブルに追加できる可能性があります。ただし、数字が構成されたときに、それらが他の数字とどのように組み合わされるかは、私にはわかりません。

  • 数値を変換する場合は、方向を気にする必要があるかもしれません。これがどのように処理されるかはわかりません (ただし、Unicode サイトにドキュメントがあります)。通常、テキストは自然な順序で表示されます。アラビア語とその関連言語の場合、自然な順序で読む場合、下位の数字が最初に表示されます: "١٢"(文字通り"12"、ただし、右から左に書くため、数字は順に表示されます"21") のように解釈する必要があります。 21ではなく12です。ただし、方向転換マークがあるかどうかはわかりません。(正確なルールは Unicode サイトのドキュメントに記載されています。UnicodeData.txt ファイルの 5 番目のフィールド (インデックス 4) がこの情報を提供します。"AN"、ヨーロッパで使用されているビッグエンディアン標準を想定できますが、よくわかりません。)

これがいかに簡単かを示すために、数字の値について UnicodeData.txt ファイルを解析する Python スクリプトを次に示します。

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 を使用している場合、このファイルはあらゆる種類の有用なテーブルを生成するための宝庫です。

于 2012-12-08T19:38:05.323 に答える
2

次のメソッドを使用して、Unicode 文字に相当する数値を取得できますQChar::digitValue

int value = QChar::digitValue((uint)0x0662);

-1文字に数値がない場合に返されます。

さらにヘルプが必要な場合は、ドキュメントを参照してください。私は c++/qt についてあまり知りません。


そのウィキペディアの記事で言及されている漢数字はに属し0x4E00-0x9FCCます。この範囲の個々の文字に関する有用なメタデータはありません。

4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
9FCC;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;

したがって、中国の数字を整数にマップしたい場合は、自分でそのマッピングを行う必要があります。

単一のシンボルが単一の数字にマップされるウィキペディアの記事のシンボルの簡単なマッピングを次に示します。

0x96f6,0x3007 = 0
0x58f9,0x4e00,0x5f0c = 1
0x8cb3,0x8d30,0x4e8c,0x5f0d,0x5169,0x4e24 = 2
0x53c3,0x53c1,0x4e09,0x5f0e,0x53c3,0x53c2,0x53c4,0x53c1 = 3
0x8086,0x56db,0x4989 = 4
0x4f0d,0x4e94 = 5
0x9678,0x9646,0x516d = 6
0x67d2,0x4e03 = 7
0x634c,0x516b = 8
0x7396,0x4e5d = 9
0x62fe,0x5341,0x4ec0 = 10
0x4f70,0x767e = 100
0x4edf,0x5343 = 1000
0x842c,0x842c,0x4e07 = 10000
0x5104,0x5104,0x4ebf = 100000000

0x5e7a = 1
0x5169,0x4e24 = 2
0x5440 = 10
0x5ff5,0x5eff = 20
0x5345 = 30
0x534c = 40
0x7695 = 200

0x6d1e = 0
0x5e7a = 1
0x4e24 = 2
0x5200 = 4
0x62d0 = 7
0x52fe = 9
于 2012-12-08T19:25:10.700 に答える