演算子のオーバーロードを使用した多項式演算
-
19-09-2019 - |
質問
演算子のオーバーロードを使用して多項式クラスの基本演算 (+、-、、/) を定義しようとしていますが、プログラムを実行するとクラッシュし、コンピューターがフリーズしてしまいます。
アップデート4
わかりました。3 つの演算が成功しました。残っているのは除算だけです。
私が得たものは次のとおりです。
polinom operator*(const polinom& P) const
{
polinom Result;
constIter i, j, lastItem = Result.poly.end();
Iter it1, it2, first, last;
int nr_matches;
for (i = poly.begin() ; i != poly.end(); i++) {
for (j = P.poly.begin(); j != P.poly.end(); j++)
Result.insert(i->coef * j->coef, i->pow + j->pow);
}
Result.poly.sort(SortDescending());
lastItem--;
while (true) {
nr_matches = 0;
for (it1 = Result.poly.begin(); it1 != lastItem; it1++) {
first = it1;
last = it1;
first++;
for (it2 = first; it2 != Result.poly.end(); it2++) {
if (it2->pow == it1->pow) {
it1->coef += it2->coef;
nr_matches++;
}
}
nr_matches++;
do {
last++;
nr_matches--;
} while (nr_matches != 0);
Result.poly.erase(first, last);
}
if (nr_matches == 0)
break;
}
return Result;
}
解決
多項式を正しく加算する関数を取得するには、次の単純なロジックをお勧めします。
polinom operator+(const polinom& P) const //fixed prototype re. const-correctness
{
polinom Result;
std::list<term>::const_iterator //fixed iterator type
i = poly.begin(), j = P.poly.begin();
while (i != poly.end() && j != P.poly.end()) {
//logic while both iterators are valid
}
//handle the remaining items in each list
//note: at least one will be equal to end(), but that loop will simply be skipped
while (i != poly.end()) {
Result.insert(i->coef, i->pow);
++i;
}
while (j != P.poly.end()) {
Result.insert(j->coef, j->pow);
++j;
}
return Result;
}
最後の部分はおそらく標準ライブラリ関数に任せることもできます
#include <iterator>
#include <algorithm>
//...
//handle remaining items in either list (if any)
std::copy(i, poly.end(), std::back_inserter(Result.poly));
std::copy(j, P.poly.end(), std::back_inserter(Result.poly));
...しかし、おそらく使用する方が簡単でしょう リスト.挿入:
Result.poly.insert(Result.poly.end(), i, poly.end());
Result.poly.insert(Result.poly.end(), j, P.poly.end());
他のヒント
while (i != poly.end() || P.i != P.End())
そこには && が必要になると思います。そうでないと、i と p.i がそれぞれの終端に同時に到達した場合にのみループが終了します。
否定を含む論理は難しいです。おそらくこれは次のように考えるのが簡単です。
while (!(i == poly.end() || j == P.End())) //while neither iterator has reached end
ブール演算によれば、これは次と同じです。
while (!(i == poly.end()) && !(j == P.End()))
while (i != poly.end() && j != P.End())
また、両方が等しい場合、イテレータをインクリメントしていないようです(無限ループにより無限に多くのメモリ割り当てが発生しますか?)。
スタイルの問題:イテレータをローカル変数として使用することをお勧めします。メソッド内で使用を開始する前に変数を「初期化」する必要がある場合は、変数をクラス メンバーにしないでください。メソッドの完了後には使用できなくなります。
また、const 参照によって引数を渡し、メンバー関数をマークすることを好みます。 定数 現在のオブジェクトを変更しない場合 (operator+
すべきではありません):
polinom operator+(const polinom& P) const;
(これにより、ローカルで使用されるイテレータのメンバーを作成する際の問題が明らかになります。インスタンスを変更することになります。)
コードには他の設計と正確さの問題がありますが、クラッシュはこの行で発生すると思います
if (i->pow > P.i->pow)
i == Poly.end() && P.i != P.End() または i != Poly.end() && P.i == P.End() の場合。i が最後の要素の後に指しているときに i を逆参照すると、クラッシュします。