/ /文字列中のマルチバイトのutf-8文字を検索するのに `strstr`を使うのは安全ですか? - c、string、utf-8、マルチバイト関数

文字列中のマルチバイトのutf-8文字を検索するのに `strstr`を使うのは安全ですか? - c、string、utf-8、マルチバイト関数

私の以前の質問に続いて: マニュアルページの免責条項にもかかわらず、 `strchr`がマルチバイト文字で動作するように見えるのはなぜですか?、私はそれを理解した strchr 悪い選択だった。

代わりに私は strstr 単一の文字を探す(マルチバイトではない char):

const char str[] = "This string contains é which is a multi-byte character";
char * pos = strstr(str, "é"); // "é" = 0xC3A9: 2 bytes
printf("%sn", pos);

Ouput:

éはマルチバイト文字です

これは私の期待するものです:私のマルチバイト文字の第1バイトの位置。

先験的に、これは標準的な使用ではありません strstr それはうまくいくようです。
この回避策は安全ですか?バグの原因となる副作用や特別なケースについて考えてみませんか?

[編集]: 私は正確に私が使用したくない wchar_t 私が扱う文字列はutf-8でエンコードされています(私はこれを認識しています 選択 議論することができますが、これは無関係の議論です)

回答:

回答№1は4

いいえ strstr マルチバイト文字を含む文字列には適していません。

マルチバイト文字を含む文字列の中にマルチバイト文字が含まれていない文字列を検索している場合、偽陽性となることがあります(使用中 シフト - ジスエンコーディング 日本語のロケールでは、strstr( "掘り出し物"、 "@some")が偽陽性になることがあります)

+---------+----+----+----+
|   c1    | c2 | c3 | c4 |  <--- string
+---------+----+----+----+

+----+----+----+
| c5 | c2 | c3 |  <--- string to search
+----+----+----+

c1の末尾の部分が誤ってc5と一致すると、誤った結果になることがあります。私は、ユニコードのサブストリングチェック機能またはマルチバイトサブストリングチェック機能を使用することをお勧めします。 (_mbsstr 例えば)

編集
OPからの更新された質問に基づいて "偽陽性はutf-8の文脈に存在する " だから答えはutf-8は上記のように文字の部分的な不一致の影響を受けず、偽陽性を引き起こすように設計されています。したがって、使用するのは完全に安全です strstr utf-8でコード化されたマルチバイト文字を使用します。


回答№2の場合は1

最近のシステムでは、utf-8(またはASCII)をマルチバイトエンコーディングとして使用していますが、この関数の使用は安全です。

厳密に準拠し、古い/エキゾチックなプラットフォームでもコードを動作させるには、追加の問題を考慮する必要があります。

まず、良いニュース:すべてのマルチバイトエンコーディングで、0バイトは状態に関係なく文字列の終わりを示します。これは、あなたの strstr クラッシュなどの原因にはなりませんが、結果が間違っている可能性があります。

たとえば、Unicodeをコード化する7ビットのきれいな方法であるUTF-7を考えてみましょう。 UTF-7はマルチバイトエンコーディングで、 シフト状態つまり、バイトがどのように解釈されるかは、それが現れるコンテキストに依存するかもしれません。例えば。 (cf. ウィキペディア) "£1AKM"は次のようにエンコードされます +AKM-AKM UTF-7で + 記号は状態や文章の解釈を変えます A。行うこと strstr(str, "AKM") 最初のAKM部分に一致します( +)これはエンコーディングの一部です £ 実際には AKM 後の部分 - (シフト状態を初期状態に戻す)。


-2の回答№3

この回避策は安全ですか?バグの原因となる副作用や特別なケースについて考えてみませんか?

1つの副作用は、if strtr() 一致するものが見つからない場合は、nullポインタ値を出力します Segmentation fault.

文字列を出力する前にポインタにNULL値があるかどうかを確認する必要があります。 それを次のようにチェックしてください:

if(pos == NULL)
printf("letter not found");
else
printf("%sn", pos);