4

いくつかのC++/STLコードを修正する必要があります。残念ながら、私はC ++の経験がほとんどなく、STLについて何も知りません。それにもかかわらず、私はそれのほとんどを終えました、しかし以下の関数はまだ私に問題を与えています:

C ++ソース:

double MyClass::CalculateAvg(const std::list<double> &list)
{
    double avg = 0;
    std::list<int>::iterator it;
    for(it = list->begin(); it != list->end(); it++) avg += *it;
    avg /= list->size();
}

C ++ヘッダー:

static double CalculateAvg(const std::list<int> &list);

これは、リストから平均値を計算することを目的としている可能性が高いですが、多くのエラーに準拠しています。Webで解決策を検索しようとしましたが、何も見つかりませんでした。誰かが私を助けてくれたら嬉しいです。

更新:迅速な返信ありがとうございます。受け入れられた答えは私のすべての問題を解決しました。

4

8 に答える 8

34

いくつかのこと:

  1. あなたは何も返しません。(追加return avg;
  2. 演算子はオブジェクトへの->ポインタ用です。リストへの参照があるので、使用しますが、使用list.begin()しませんlist->begin()(他のメンバー関数についても同じです)
  3. イテレータは、const_iteratorではなく、である必要がありiteratorます。

いずれの場合も、次のことを行う必要があります。

return std::accumulate(list.begin(), list.end(), 0.0) / list.size();

オプションlist.size() == 0で、ユースケースでそれが可能かどうかを確認します。

于 2010-02-01T13:37:39.720 に答える
14

したがって、最初のエラーは次のとおりです。

std::list<int>::iterator it;

整数のリストでイテレータを定義し、それを使用してdoubleのリストで反復します。また、イテレータは非定数リストでのみ使用できます。定数演算子が必要です。あなたは書くべきです:

std::list<double>::const_iterator it;

最後に、値を返すのを忘れました。

編集:私は見ませんでしたが、あなたはリストを参照として渡しますが、それをポインタとして使用します。したがって、すべてlist->list.

于 2010-02-01T13:33:11.210 に答える
2

@PierreBdRの回答に加えて、list-> size()が0より大きいことも確認する必要があります。

ここの直前

  avg /= list.size();

追加

 if (list.size()>0) 
    //avg code here.

または、引数として受け取ったリストが空であってはならないことを文書化します。

   assert(list.size()>0)
于 2010-02-01T13:38:36.007 に答える
2

イテレータが同じタイプのリストを参照するように編集するのではなく、イテレータタイプをテンプレートパラメータとして使用する汎用アルゴリズムとしてコードを記述する方がはるかに優れています。

std::listまた、元のコード投稿された回答のほとんどには、かなり深刻な効率の問題があることにも注意してください。リストの一般的な実装では、リストを1回繰り返して値を合計してから、次のように繰り返します。要素の数を数えます。理論的には、要素を反復処理せずに一定時間で実行list.size() できますが、実際にはそうなることはめったにありません(list::size()またはについて一定の複雑さを持つことができますがlist::splice、両方に対して同時に行うことはできません)。

私は次のようなコードを書きます:

template <class fwdit> 
typename fwdit::value_type arithmetic_mean(fwdit begin, fwdit end) { 

    typedef typename fwdit::value_type res_type;

    res_type sum = res_type();
    size_t count = 0;

    for (fwdit pos = begin; pos!= end; ++pos) { 
        sum += *pos;
        ++count;
    }
    return sum/count;
}

std::listこれは一般的なものであるため、これが不適切な選択であることに気付いた場合でも、(変更されずに)機能し続けますstd::vector。同様に、doubleの代わりにintの算術平均が必要な場合は、それも処理できます(ここでも、コードを変更する必要はありません)。第3に、(上記で示唆したように)ライブラリの実装がst::list::size()たまたま線形であったとしても、リストをトラバースするのは1回だけなので、元のコード(の動作バージョン)の約2倍の速度になる可能性があります。

もちろん、キャッシングはそれに影響を与える可能性があります-小さなリストを平均すると、最初のトラバーサルはリスト全体をキャッシュにプルするので、2番目のトラバーサルは通常はるかに高速になります(したがって、2番目のトラバーサルを排除しても多くの時間を節約します)。

于 2010-02-01T16:04:05.330 に答える
1

パスインしますが、イテレータstd::list<double>を作成しますか?std::list<int>そして、あなたのプロトタイプもかかりますstd::list<int>

于 2010-02-01T13:32:54.520 に答える
1

Maurits Rijkが言ったように、あなたは平均を返していません。さらに、コンパイルにはどのようなエラーがありますか?

于 2010-02-01T13:33:56.633 に答える
1

はポインタではなく参照であるため、間接参照演算子listは必要ありませんが、演算子だけが必要です。->.it = list.begin()

さらに、他のすべての人が指摘しているように、リストとそのイテレータのテンプレートタイプパラメータはすべて一致する必要があります:<int>または<double>。この関数は元々、のリストを受け入れるように作成されたようdoubleです。

于 2010-02-01T13:33:59.947 に答える
1

あなた自身のための練習として。動作させたら、for_eachに変換する必要があります。長期的には理解しやすいです。

- 編集 -

Accumulateは、2進数演算を対象としているため、より優れています。

于 2010-02-01T13:36:57.863 に答える