1

これは、本当に問題のある質問があります。あなたの意見に興味があります。構文エラーがある場合は、擬似コードを使用して説明する意図を示します。

for ループを使用するプログラムがあります。

for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
 ABC...
}

ここで、プログラムを反復する別の方法を追加したいと思います。

for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
 ABC...
}

だから私はif文を書いた

if(a == true){
 for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
  ABC...
 }
}else{
 for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
  ABC...
 }
}

しかし、どういうわけか、コードを複製したため、気に入らなかったのです。

  ABC...

もちろん、すべてをループ内からメソッドに移動して、そのメソッドのみを呼び出すこともできます。しかし、私は疑問に思っていました

switch(a){
case(true):
 for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
 break;
default:
 for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
 break; 
}

私はここでそれを使用していたので、可能であり、可能であれば便利で理にかなっています. もちろん、必ずしもswitch-case他のメカニズムである必要はありません。しかし、私の意図は、私の観点からすると、atomic

for( ; ; ) {
...
}

本体を組み直します。

4

6 に答える 6

4

ABC関数 ( extractメソッド) を作成し、それを呼び出します。

于 2013-07-04T10:08:19.310 に答える
3

一部の言語には、このようなパターンを簡単に再利用可能にするメカニズムがあります。たとえば、C# では次のように記述できます。

IEnumerable<Frame> Frames1() {
   for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
    yield return framelist[framepos];
   }
}
IEnumerable<Frame> Frames2() {
  for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
    yield return framelist[framepos];
   }
}

そして、これらの反復パターンを他のオブジェクトと同様にファースト クラス オブジェクトとして扱うことができます。

foreach(var frame in a? Frames1() : Frames2()) {
   ABC...
}

このような機能を使用すると、C のループ用の低レベルのエラーが発生しやすいプリミティブである愚かなボイラープレートのような実装の詳細を回避できます。

C++ にはそのような構文機能はありませんが、反復パターンを再利用するための同様の確立されたメカニズムである反復子もあります。ただし、反復子の作成は C# ほど簡単ではありません:(

しかし、標準のコンテナーは既に適切なイテレーターを提供しています。その後、標準ライブラリで提供されている多くの既存の反復パターンを再利用できます。

std::vector<int> v = ...;
std::set<int> s = ...;
auto are_equal = std::equal(v.begin(), v.end(), s.begin(), s.end());

同様に、優れた C++ ライブラリも適切なイテレータを提供します。(ええ、それで頑張ってください。「C++ ライブラリ」を書いている人の大部分は C++ を知らないようです)

于 2013-07-04T10:18:04.233 に答える
2

ABC を関数にしたくない場合は、2 つの異なる for ループを切り替えて、代わりに 3 つの関数を記述できます。

int initFramepos( int a ) 
{ 
    return( a ? 1 : framelist.first );
}

int checkFramepos( int frame_pos, int a )
{
    return( a ? frame_pos < frame_size ? framelist.hasNext );
}

int incrFramepos( int frame_pos, int a )
{
    return( a ? frame_pos+1 ? framelist.getNext );
}

次に、for ループは次のようになります。

for( frame_pos = initFramepos( a ); checkFramepos( frame_pos, a ); frame_pos = incrFramepos( frame_pos, a ) )
{
     ABC
}
于 2013-07-04T10:21:01.130 に答える
2

明確な解決策 ( C++ コードの場合- これは C では機能しません) は、特定のケースに合わせて反復子クラスの実装を作成することです。次に、反復子の観点からクライアント コードを記述し、実装方法に関係なく、反復の意味を決定できます (クライアント コードをまったく変更せずに、いつでも反復の意味を決定できます)。

これを実行して と を特化するstd::beginstd::end、おまけとして std のイテレータ アルゴリズム ライブラリ全体を使用できるようになります: ( 、sortcopyfind/find_iffor_eachall_ofany_if最も便利です。私の頭の中で)。transformaccumulate

他の解決策については、マクロを使用しないでください。マクロを使用すると、脆弱なコードになり、見にくい多くの警告が表示されます。経験則として、C++ でマクロを使用することは、(それに近い) 最後に考えられる解決策です。

于 2013-07-04T11:05:31.007 に答える
1

ここで説明しているのは、まさに戦略パターンが解決しようとしていた問題です。基本的に、ここで行う必要があるのは、各ループをクラス内のメソッドとして作成し、そのうちの 1 つを戦略として設定することです。もちろん、いつでも戦略を切り替えることができます。

次のようになります。

 class Strategy {
    virtual void func () = 0;
 };

.

 class StrategyA : public Strategy {
    virtual void func () {
         for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
        ABC...
         }
    }
};

.

class StrategyB : public Strategy {
virtual void func () {
        for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
            //ABC...
        }
    }
};

.

class StrategyToTake {

private:
Strategy* strategy;

public:
void execute () {strategy->func();}
void setStrategy (Strategy* newStrategy) {this.strategy = newStrategy;}

};

.

于 2013-07-04T10:47:20.693 に答える