1

異なるエンコーディング (UTF-8 から UTF-16 など) の文字列間で変換する関数を作成する場合、エラー (無効な入力 UTF-8 バイト シーケンスなど) を処理する最良の方法は何でしょうか? 例外をスローしたり、エラー コードを返したりしますboolか?

// Throws a C++ exception on error. 
std::wstring ConvertFromUtf8ToUtf16(const std::string& utf8);

// Returns true on success, false on error.
bool ConvertFromUtf8ToUtf16(std::wstring& utf16, const std::string& utf8);

例外を使用すると、連鎖した関数呼び出しを行うことができます (関数の戻り値が他の関数/メソッドの入力として使用される場合)。

しかし、この場合に例外を使用することが適切かどうかはわかりません。Eric Lippertが質の高いブログ記事で厄介な例外(および関連するInt32.Parse()/TryParse()例)と呼んでいるものについて考えていました。

たとえば、例外が使用されている場合、呼び出し元は関数呼び出しをtry/catchブロックでラップして、無効な UTF-8 入力のケースをチェックする必要があります。

try
{
   wstring utf16 = ConvertFromUtf8ToUtf16(utf8);
}
catch(const Utf8ConversionException& e)
{
   // Bad UTF-8 byte sequence
   ...
}

これは私には理想的ではないようです。

おそらく最善の方法は、両方のオーバーロードを提供することです (スローしないオーバーロードで変換コードを実装し、スローするオーバーロードではスローしないバージョンを呼び出し、エラーの場合は戻りコードが例外をスローします)?

4

3 に答える 3

2

ガイドラインの 1 つは、返されたエラー コードを確認する必要があることをユーザーが無視したり、知らない場合にどうなるかを検討することです。

  • コードがエラーに直面しても理論的に続行できる場合、エラーを返すことは合理的であると見なすことができます。そして、あなたが言及したように、コードはきれいに見えます。
  • エラーを無視すると、後で非常に悪い動作が発生する可能性がある場合は、例外をスローすることをお勧めします。
  • エラー コードの簡潔さと潜在的なエラーの認識をプログラマに強いることのバランスをとる3 つ目の選択肢は、関数がエラー コードへの参照を要求するようにすることです。これは、エクスポートされたライブラリや、例外を効率的に処理しない (ほとんどが古い) コンパイラでもうまく機能します。

    StringConversionResult result; // Could be a "success" bool

    wstring utf16 = ConvertFromUtf8ToUtf16(utf8, result);

于 2012-09-15T15:44:59.237 に答える
0

この関数がライブラリからエクスポートされる場合は、リターン コードを使用します。ライブラリとクライアントが異なる C/C++ ランタイム ライブラリでビルドされている場合、エクスポートされた関数から例外をスローすると、プログラムがクラッシュする可能性があります。通常、これは未定義の動作です。

内部で使用する場合は、例外の方が適していると思います。あなたが話しているケースでは、呼び出し元が catch ブロックを使用していない場合、プログラムがすぐにクラッシュします (未処理の例外)。これはより良いことであり、将来のある時点で未定義の結果でプログラムの実行を続行することをお勧めします。

于 2012-09-15T15:49:07.623 に答える
0

選択肢は 3 つだけです。1 つ目は、「すべての障害をエラー コードポイントで置き換える」です。Unicode 標準では、いくつかの置換コードポイントが提供されています。これは、いくつかのシナリオでは問題ありません。2 つ目は、例外をスローすることです。3 つ目は、失敗時に呼び出されるエラー関数オブジェクトを提供することです。例えば、

bool fail = false;
std::u16string str = ConvertFromUTF8ToUTF16(utf8, [&] {
    return u16"default";
    // or
    throw std::runtime_error("fail");
    // or
    fail = true;
});

要点は、どのシナリオでも、失敗のチェックをユーザーに依存しないということです。ユーザーが何もしない場合、関数が続行されないか、コンパイラが泣くか、関数が続行しても問題ありません。

エラーコードを返すことはオプションではありません.これは明らかに恐ろしいほどエラーが発生しやすいです.

于 2012-09-15T15:52:02.643 に答える