20

Unicode 文字列の各文字を反復処理し、各サロゲート ペアを処理し、文字列を 1 つの単位(1 つの書記素)として結合したいと考えています。

テキスト「 नमस्ते」はコードポイントで構成されU+0928, U+092E, U+0938, U+094D, U+0924, U+0947U+0938U+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 は、BreakIteratorICU から使用するヒントを与えました。これは、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;
}
4

3 に答える 3

13

これには ICU BreakIteratorを使用できるはずです(Java バージョンと機能が同等であると仮定した文字インスタンス)。

于 2011-01-02T16:33:52.517 に答える
2

Glib のustringクラスは、utf-8 を使用しても問題ない場合、utf-8 文字列を提供します。に類似するように設計されていますstd::string。utf-8 は Linux のネイティブであるため、タスクは非常に簡単です。

int main()
{
    Glib::ustring s = L"नमस्ते";
    cout << s.size();
}

通常どおり文字列の文字を反復処理することもできますGlib::ustring::iterator

于 2011-01-02T16:49:06.667 に答える
0

ICU には非常に古いインターフェースがあり、Boost.Locale の方がはるかに優れています。

#include <iostream>
#include <string_view>

#include <boost/locale.hpp>

using namespace std::string_view_literals;

int main()
{
    boost::locale::generator gen;
    auto string = "noël "sv;
    boost::locale::boundary::csegment_index map{
        boost::locale::boundary::character, std::begin(string),
        std::end(string), gen("")};
    for (const auto& i : map)
    {
        std::cout << i << '\n';
    }
}

テキストはこちらから

于 2017-08-09T04:41:35.683 に答える