34

これは、美しいコードの章に関連しています。そしてその章で私はネストされたifsについて読みました。

if作者は、バグの発生源であり、読みにくいものとして、深くネストされたsについて話していました。そして、彼はネストされたifsをcaseステートメントとデシジョンテーブルに置き換えることについて話していました。

ifネストされたsをcaseselect case)とデシジョンテーブルで削除する方法を誰かが説明できますか?

4

11 に答える 11

27

スイッチ/ケースステートメントについて具体的に質問しているため、質問への直接の回答ではありませんが、同様の質問があります。

「if」ステートメントを反転して入れ子を減らす

これは、ネストされた if を、戻り値に落ち着く前により多くのことを徐々にチェックするのではなく、早期に戻るガード ステートメントに置き換えることについて述べています。

于 2008-12-03T13:13:44.380 に答える
12

私がいつもやろうとしている1つの例は、このようにネストされたものを置き換えることです(実際、これはそれほど悪くはありませんが、野生では8または9レベルまで見たことがあります)。

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

これとともに:

switch (i) {
    case 1:
        // action 1
        break;
    case 2:
        // action 2
        break;
    case 3:
        // action 3
        break;
    default:
        // action 4
        break;
}

また、アクションをできるだけ小さくして(これには関数呼び出しが最適です)、switchステートメントを圧縮したままにします(したがって、4ページ先に進んでその終わりを確認する必要はありません)。

デシジョンテーブルは、後で実行する必要のあるアクションを示すフラグを設定しているだけだと思います。「後で」セクションは、これらのフラグに基づくアクションの単純な順序付けです。私は間違っている可能性があります(それは最初でも最後でもありません:-)。

例は次のようになります(そのアクションが非常に単純であるため、フラグ設定フェーズは複雑になる可能性があります):

switch (i) {
    case 1:
        outmsg = "no paper";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    case 2:
        outmsg = "no ink";
        genmsg = true;
        mailmsg = true;
        phonemsg = false;
        break;
    default:
        outmsg = "unknown problem";
        genmsg = true;
        mailmsg = true;
        phonemsg = true;
        break;
}

if (genmsg)
    // Send message to screen.
if (mailmsg)
    // Send message to operators email address.
if (phonemsg)
    // Hassle operators mobile phone.
于 2008-12-03T13:31:00.430 に答える
8

連鎖したifはどうですか?

交換

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

if (condition1) {
   do1;
} else if (condition2) {
   do2;
} else if (condition3) {
   do3;
}

これは、複雑な条件のswitchステートメントによく似ています。

于 2008-12-03T13:46:19.417 に答える
7

条件をブール値にしてから、それぞれの場合にブール式を記述します。

コードが次の場合:

if (condition1)
{
    do1
}   
else
{
    if (condition2)
    {
        do2
    }
    else (condition3)
    {
        do3;

    }
}

次のように書くことができます:

bool cond1=condition1;
bool cond2=condition2;
bool cond3=condition3;

if (cond1) {do1;}
if (!cond1 and cond2) {do2;}
if (!cond1 and cond3) {do2;}
于 2008-12-03T13:36:57.190 に答える
3

デシジョン テーブルについては、この質問に対する私の回答を参照するか、 Code Complete 2の第 18 章をお読みください。

于 2008-12-03T13:57:52.357 に答える
1

デシジョンテーブルは、コード自体ではなく、データ構造に条件付きロジックを格納する場所です。

したがって、これの代わりに(@Paxの例を使用して):

if (i == 1) {
    // action 1
} else {
    if (i == 2) {
        // action 2
    } else {
        if (i == 3) {
            // action 3
        } else {
            // action 4
        }
    }
}

あなたはこのようなことをします:

void action1()
{
    // action 1
}

void action2()
{
    // action 2
}

void action3()
{
    // action 3
}

void action4()
{
    // action 4
}

#define NUM_ACTIONS 4

// Create array of function pointers for each allowed value of i
void (*actions[NUM_ACTIONS])() = { NULL, action1, action2, action3 }

// And now in the body of a function somewhere...
if ((i < NUM_ACTIONS) && actions[i])
    actions[i]();
else
    action4();

の可能性iが小さい整数でない場合は、配列のith要素に直接アクセスする代わりにルックアップテーブルを作成できます。actions

この手法は、数十の可能な値を決定する場合に、ネストされたifsまたはステートメントよりもはるかに便利になります。switch

于 2008-12-03T14:19:19.210 に答える
0

また、 Visitorパターンの使用を検討することもできます。

于 2008-12-03T14:15:24.193 に答える
0

if ステートメントと switch ステートメントは、純粋に OO ではありません。それらは条件付きの手続き型ロジックですが、非常にうまく機能します。OO アプローチを強化するためにこれらのステートメントを削除する場合は、「状態」パターンと「記述子」パターンを組み合わせます

于 2008-12-03T13:58:28.377 に答える
0

ネストされた if は、論理演算子 AND と同等です

if (condition1)
{
    if (function(2))
    {
        if (condition3)
        {
            // do something
        }
    }
}

同等のコード:

if (condition1 && function(2) && condition3)
{
    // do something
}

どちらの場合も、式が false と評価されると、後続の式は評価されません。たとえば、condition1 が false の場合、function() は呼び出されず、condition3 は評価されません。

于 2013-10-03T10:43:53.783 に答える
-1

一部の言語で許可されている別の例はこれです

           switch true{
            case i==0
              //action
            break

            case j==2
             //action
            break

            case i>j
             //action
            break
           }
于 2008-12-03T13:39:24.173 に答える