0

STLリンクリストに構造体を取り込むプログラムがあり、リスト上のノード(現在イテレーターを介して使用しているノード)から構造体メンバーを渡そうとしています。私が達成しようとしていることの1つは、移動平均を計算する関数です。構造体にカウントと合計を格納してから出力時に平均を計算するのではなく、構造体にカウントと平均を格納して、平均が再計算された後に数量値を破棄したいと思います。私の構造は次のようになります:

struct mystruct 
{
    string item;
    long avg;
    short count;
} data;

itこれらの構造体は、リスト内を移動できるイテレータ、を使用してリストに格納されます。itリストをトラバースし、平均を計算したいデータのノードと等しい場合、これは平均関数を呼び出す適切な方法でしょうか?

// prior to running the code below, the `count` and `avg` members for the 
// struct at iterator location `it` are both 1 and 100 respectively

long qty = 50;
calc_average(it->count, it->avg, qty);

cout << "The current count is " << it->count << endl; 
  // Outputs 'The current count is 2'
cout << "The current average is " << it->avg << endl; 
  // Outputs 'The current average is 75'


void calc_average(short &count, long &avg, long quant)
{
    avg = ( (avg * count) + quant ) / (count + 1);
    count++;
}

これは正しいようですか?STLリストを使用してこれを実装しようとしていますが、独自のリンクリストクラスを実装するよりも混乱しているようです。構造とイテレータが実際にどのように機能するか、そして実際に何がどのように受け渡されているかについて、私は混乱していると思います。コーディングはまだ私にはかなり新しいので、これの多くは学習プロセスです...

ありがとう!

4

4 に答える 4

3

それがリスト内のオブジェクトのタイプであると仮定するとX、次のようなことができます。

void DoSomething(X& object) {
  object.count, object.avg;
}
void DoSomethingElse(int& count, int& average) {
  ...
}

int main() {
   ...
   for(std::list<X>::iterator it=myList.begin(), end=myList.end(); it != end; ++it) {
     DoSomething(*it); // how I'd do it
     DoSomethingElse(it->count, it->avg); // Equally valid way that you did it
   }
   ...
}

覚えとけ:

  • container.begin()最初の要素へのポインタです
  • container.end()最後から1つ前の要素へのポインタです
  • *it指示された要素への参照です
  • it != container.end()あなたが最後にいるかどうかを知る方法です
  • it->xポインテッド要素のメンバーです
  • コンテナからオブジェクトを削除すると、いくつかの要因によっては、未処理のイテレータが無効になる場合があります。
  • ++itおそらくより効率的ですit++

編集:OPは尋ねます:

リストを反復処理してすべてのノードでcalc_averageを実行するのではなく、リストを反復処理して特定のアイテム値を探します。関心のあるものを見つけたら、その特定のノードでcalc_average関数を呼び出しています。forループは必要ありません。代わりに、目的のイテレータに到達し、それを* it経由で渡してDoSomethingを無効にしますか?

あなたはそれが今どのように機能するかを理解していると思います。示されたノードを検索するためのコードと、関数を呼び出すためのその他のコードがあります。

   std::list<X>::iterator it, end;
   for(it=myList.begin(), end=myList.end(); it != end; ++it) {
     // Look for the special node:
     if( it->magicValue == 42 ) {
       // We found it!
       break;
     }
   }

    // Either it is equal to end (boo!) or it points to the special node (yay!)
   if( it == end ) {
      std::cerr << "Could not find special node!\n";
   }
   if( it != end ) {
      DoSomething(*it);
   }
于 2012-10-22T21:05:45.120 に答える
1

イテレータは、リスト内の要素へのポインタと考えてください。したがって、calc_average関数を個々のメンバーに作用させる代わりにmystruct、オブジェクトへの参照を取得して、それをmystruct使用して何かを実行することができます。

例えば:

void do_work( mystruct& s )
{
  ++s.count;
}

std::list<mystruct> mylist;

// populate list

std::for_each( mylist.begin(), mylist.end(), do_work );

for範囲ベースのループでも同じ効果を得ることができます

for( auto& elem : mylist ) {
  do_work( elem );
}

calc_average関数を次のように書き直します

void calc_average( mystruct& s, long quant )
{
    s.avg = ( (s.avg * s.count) + quant ) / (s.count + 1);
    s.count++;
}

範囲ベースのforループで使用するのは簡単ですが、使用するには、パラメーターをバインドするstd::for_eachために使用する必要があります。std::bindquant

std::for_each( mylist.begin(), mylist.end(), 
  std::bind( calc_average, std::placeholders::_1, qty ) );
于 2012-10-22T21:10:24.993 に答える
0

はい、それはすべて私には正しいようです。イテレータ(特に標準コンテナのイテレータ)は単なるポインタと考えることができますが、実際にはポインタのように見えるクラスです。それでも、それらはポインタと考えることができます。

于 2012-10-22T21:13:38.223 に答える
0

現在、動的コンテンツを使用していますが、SPRITE構造std ::listcharacters_spr;があることがわかりました。スプライト文字で文字を宣言してから使用します

characters_spr.push_back(character)

次に、forループを使用してリストを反復処理します

for(SPRITE &character : characters_spr){
   somefunction(character, ....);
}

いくつかの機能で私はいくつかの機能を持っています(SPRITE&spr、......................)

また、somefunctionが呼び出されると、リスト内の文字の文字データが更新されます。

于 2021-01-14T23:03:43.527 に答える