1

私は次のようなコードをよく書いています。

set<int> affected_items;
while (string code = GetKeyCodeFromSomewhere())
{
    if (code == "some constant" || code == "some other constant") {
        affected_items.insert(some_constant_id);
    } else if (code == "yet another constant" || code == "the constant I didn't mention yet") {
        affected_items.insert(some_other_constant_id);
    } // else if etc...
}
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++)
{
    switch(*it)
    {
        case some_constant_id:
           RunSomeFunction(with, these, params);
        break;
        case some_other_constant_id:
           RunSomeOtherFunction(with, these, other, params);
        break;
        // etc...
    }
}

このコードを書くことになった理由は、関数を実行させる可能性のある複数のキー コードを受け取ったとしても、2 番目のループで関数を 1 回だけ実行する必要があるからです。

これは、最善の方法とは思えません。もっときちんとした方法はありますか?

4

4 に答える 4

2

1 つのアプローチは、文字列からブール値へのマップを維持することです。主なロジックは次のようなものから始めることができます:

if(done[code])
    continue;
done[code] = true;

その後、コードを特定したらすぐに適切なアクションを実行できます。

もう 1 つの方法は、実行可能なもの (オブジェクト、関数ポインターなど) を一種の「to do リスト」に格納することです。例えば:

while (string code = GetKeyCodeFromSomewhere())
{
    todo[code] = codefor[code];
}

各コード値に対して、適切な関数ポインター、または共通の基本クラスからサブクラス化されたオブジェクトを含むように codefor を初期化します。同じコードが 2 回以上表示された場合、todo の適切なエントリは、それが既に持っていたのと同じ値で上書きされます。最後に、todo を反復処理し、そのすべてのメンバーを実行します。

于 2008-10-28T01:46:43.493 に答える
1

セット内の実際の値を気にしていないように見えるので、int の設定ビットに置き換えることができます。線形時間検索ロジックをログ時間検索ロジックに置き換えることもできます。最終的なコードは次のとおりです。

// Ahead of time you build a static map from your strings to bit values.
std::map< std::string, int > codesToValues;
codesToValues[ "some constant" ] = 1;
codesToValues[ "some other constant" ] = 1;
codesToValues[ "yet another constant" ] = 2;
codesToValues[ "the constant I didn't mention yet" ] = 2;

// When you want to do your work
int affected_items = 0;
while (string code = GetKeyCodeFromSomewhere())
    affected_items |= codesToValues[ code ];

if( affected_items & 1 )
    RunSomeFunction(with, these, params);
if( affected_items & 2 )
    RunSomeOtherFunction(with, these, other, params);
// etc...
于 2008-10-28T01:29:57.490 に答える
1

確かにきれいではありませんが、その特定の関数を呼び出したかどうかを示す一連のフラグを維持できます。そうすれば、セットに保存する必要がなくなり、フラグだけが得られます。

(おそらくその書き方から)、コンパイル時に固定されたさまざまな if/else ブロックの数があるため、ビットセットを使用してこれを非常に簡単に行うことができます。

于 2008-10-28T01:30:14.963 に答える
0

明らかに、特定の状況に依存しますが、呼び出す関数が既に実行されているかどうかを追跡し、必要に応じて早期に終了する方がよい場合があります。

于 2008-10-28T03:41:22.640 に答える