Unicode 文字列の各文字を反復処理し、各サロゲート ペアを処理し、文字列を 1 つの単位(1 つの書記素)として結合したいと考えています。
例
テキスト「 नमस्ते」はコードポイントで構成されU+0928, U+092E, U+0938, U+094D, U+0924, U+0947
てU+0938
いU+0947
ます。
static void Main(string[] args)
{
const string s = "नमस्ते";
Console.WriteLine(s.Length); // Ouptuts "6"
var l = 0;
var e = System.Globalization.StringInfo.GetTextElementEnumerator(s);
while(e.MoveNext()) l++;
Console.WriteLine(l); // Outputs "4"
}
これで .NET が完成しました。Win32もありますCharNextW()
#include <Windows.h>
#include <iostream>
#include <string>
int main()
{
const wchar_t * s = L"नमस्ते";
std::cout << std::wstring(s).length() << std::endl; // Gives "6"
int l = 0;
while(CharNextW(s) != s)
{
s = CharNextW(s);
++l;
}
std::cout << l << std::endl; // Gives "4"
return 0;
}
質問
私が知っている両方の方法は、Microsoft に固有のものです。それを行うポータブルな方法はありますか?
- ICU について聞いたことがありますが、すぐに関連するものを見つけることができませんでした (
UnicodeString(s).length()
それでも 6 が返されます)。ICUの関連する機能/モジュールを指すのは受け入れられる答えでしょう。 - C++ には Unicode の概念がないため、これらの問題に対処するための軽量のクロスプラットフォーム ライブラリが受け入れられる答えになります。
編集:ICUを使用した正解
@McDowell は、BreakIterator
ICU から使用するヒントを与えました。これは、Unicode を扱うための事実上のクロスプラットフォーム標準と見なすことができると思います。その使用法を示すサンプル コードを次に示します (例は 驚くほどまれであるため)。
#include <unicode/schriter.h>
#include <unicode/brkiter.h>
#include <iostream>
#include <cassert>
#include <memory>
int main()
{
const UnicodeString str(L"नमस्ते");
{
// StringCharacterIterator doesn't seem to recognize graphemes
StringCharacterIterator iter(str);
int count = 0;
while(iter.hasNext())
{
++count;
iter.next();
}
std::cout << count << std::endl; // Gives "6"
}
{
// BreakIterator works!!
UErrorCode err = U_ZERO_ERROR;
std::unique_ptr<BreakIterator> iter(
BreakIterator::createCharacterInstance(Locale::getDefault(), err));
assert(U_SUCCESS(err));
iter->setText(str);
int count = 0;
while(iter->next() != BreakIterator::DONE) ++count;
std::cout << count << std::endl; // Gives "4"
}
return 0;
}