2016-04-17 15 views
2

mbrtowc()を使用して、Cでマルチバイト文字列を使ってフォワードを繰り返すことができます。しかし、もし私が後方に反復したいのであればどうでしょうか?言い換えれば、以前の有効なマルチバイト文字をどのように見つけるか。私は、次の方法を試してみましたが、それは、少なくとも部分的にデフォルトのEN_US.UTF-8ロケールを使用して、私のUbuntuシステム上で動作します:後方反復マルチバイト文字列 - C

 char *str = "\xc2\xa2\xc2\xa1xyzwxfd\xc2\xa9", *tmp = NULL; 
     wchar_t wc = 0; 
     size_t ret = 0, width = 1; 
     mbstate_t state = {0}; 

     //Iterate through 2 characters using mbrtowc() 
     tmp = str; 
     tmp += mbrtowc(&wc, tmp, MB_CUR_MAX, &state); 
     tmp += mbrtowc(&wc, tmp, MB_CUR_MAX, &state); 

     //This is a simplified version of my code. I didnt test this 
     //exact code but this general idea did work. 
     for(tmp--; (ret = mbrtowc(&wc, tmp, width, &state)) == (size_t)(-1) || ret == (size_t)(-2); width++, tmp--) 
      if(width == MB_CUR_MAX) printf("error\n"); 

     printf("last multibyte character %lc\n", wc); 

アイデアは単純です、私たちのように、有効なマルチバイト文字を見つけるまでちょうど1バイトで後方反復しますmbrtowc()によって定義されます。私の質問は、可能なマルチバイトロケールで動作するか、特殊なプロパティを持つエンコーディングのみに頼ることができます。さらに具体的には、mbstate_tが誤って使用されています。方向の変更がmbstate_tの有効性に影響を与える可能性がありますか?私は現在、 'ret'が不完全で無効なマルチバイト文字の定義に依存すると仮定しているため、 'ret'は(size_t)( - 1)または(size_t)( - 2) 。

+0

もしあなたが肯定的なのであれば、UTF8ストリングを処理するだけでいいです。*任意の* UTF8シーケンスの最初のバイトはユニークです。 – usr2564301

+3

しかし、レガシー2バイトエンコーディングの場合、実際には最初から開始せずに、逆方向に反復することは一般的に不可能です。 –

+0

@RadLexusアドバイスをありがとうが、残念ながら私はその前提を作ることはできません。 –

答えて

5

理論上可能なマルチバイトエンコーディングに対処する必要がある場合は、逆方向に反復することはできません。マルチバイトエンコーディングが、有効なマルチバイトシーケンスの適切な接尾辞が有効なマルチバイトシーケンスでないという特性を有するという要件はない。 (有効なシーケンスの途中で開始し、次のシーケンスに進むマルチバイトシーケンスを認識する可能性があるため、アルゴリズムにはさらに強力なプロパティが必要です)。

また、 )マルチバイトエンコーディングにシフトステートがある場合、マルチバイトステート。状態を変更するマルチバイトシーケンスをバックアップすると、以前の状態が何であるか分かりません。

UTF-8はこれを念頭に置いて設計されました。シフトステートはなく、シーケンスを開始できるオクテット(バイト)を明確にマークします。したがって、マルチバイトエンコーディングがUTF-8であることがわかっている場合は、簡単に後方に反復することができます。 0x80-0xBFの範囲にない文字を逆方向にスキャンするだけです。 (UTF-16とUTF-32もどちらの方向にも簡単に反復できますが、2バイトまたは4バイトのコード単位として読み込む必要があります。調整が正しくないコードポイントが正しいコードポイントになる可能性が高いからです)

マルチバイトエンコーディングがUTF-8であることがわからない場合は、後方に反復する強力なアルゴリズムはありません。あなたができることは、順方向の繰り返しであり、各キャラクターの開始位置とmbstateを覚えておいてください。

最近、Unicodeエンコーディング以外のマルチバイトエンコーディングをサポートする理由はほとんどありません。

0

UTF-8では、encoding propertyの最初のバイトに続く追加バイトの恩恵を受けることができます。マルチバイト文字の追加バイト(およびそれらのみ)は10xx xxxxで始まります。

だから、もしあなたが後方に行くと、char cは(c & 0xC0)==0x80となり、スキップすることができます。

他のマルチバイトエンコーディングでは、リードとそれに続くバイトがranges that overlapにあるような簡単な解決策はありません。

関連する問題