Я нахожусь в процессе написания полиномиального класса и перегружен оператор +. Я задал вопрос несколько дней назад относительно фактического процесса перегрузки, и получил отличный ответ. Тем не менее, мой вопрос сейчас касается реальной функции моей программы.
Мне нужно добавить два введенных пользователем полинома вместе. Когда кто-то добавляет многочлены, он должен добавлять только одинаковые термины, даже если два многочлена различаются по размеру. Моя программа работает нормально, если первый введенный полином больше второго, но выдает ошибку, если первый полином меньше второго. Чтобы быть более конкретным … Я заметил, что это, кажется, оставить один термин. Кроме того, кажется, что складываются два одинаковых термина, а затем распечатывается с другим показателем степени. Например :
2x ^ 3 + 3x ^ 3 = 5x ^ 2.
Для справки, это мой предыдущий вопрос относительно этой программы: Перегрузка + оператор с классами, содержащими указатели на массив (C ++)
Некоторая помощь будет принята с благодарностью.
Мой код:
#include<iostream>
#include<stdexcept>
using namespace std;
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
class Polynomial
{
friend istream& operator>>(istream& in, Polynomial& p);
friend ostream& operator<<(ostream& out, const Polynomial& p);
public:
Polynomial(int = 10);
~Polynomial();
void assignExponent();
Polynomial operator+(const Polynomial& other);
private:
int SIZE;
int *exponents;
int *polyPtr;
};
#endif
//CONSTRUCTOR
Polynomial::Polynomial(int arraySize)
{
if(arraySize > 0)
SIZE = arraySize;
else
{
cout << "Array size must be greater than 0. Program will now "<< "Terminate..." << endl;
system("pause");
exit(0);
}
polyPtr = new int[SIZE];
exponents = new int[SIZE];
for(int i = 0; i<SIZE; i++)
polyPtr[i] = 0;
assignExponent();
};
//DESTRUCTOR
Polynomial::~Polynomial()
{
delete [] polyPtr;
};
//STREAM INSERTION
istream& operator>>(istream& in, Polynomial& p)
{
for(int i = 0; i<p.SIZE; i++)
{
in >> p.polyPtr[i];
}
return in;
};
//STREAM EXTRACTION
ostream& operator<<(ostream& out, const Polynomial& p)
{
int exponent;
for(int i = 0; i<p.SIZE; i++)
{
exponent = (p.SIZE - 1) - i;
if(p.polyPtr[i] != 1)
{
if(exponent > 0 && exponent != 1)
out << p.polyPtr[i] << "x^" << exponent << " + ";
if(exponent == 1)
out << p.polyPtr[i] << "x" << " + ";
if(exponent == 0)
out << p.polyPtr[i];
}
//In order to not display coefficient if = 1
else
{
if(exponent > 0 && exponent != 1)
out << "x^" << exponent << " + ";
if(exponent == 1)
out << "x" << " + ";
if(exponent == 0)
out << p.polyPtr[i];
}
}
return out;
};
//Assigns a value for exponent
void Polynomial::assignExponent()
{
for(int i = 0; i<SIZE; i++)
{
exponents[i] = (SIZE - 1) - i;
}
};
//OVERLOAD OF + OPERATOR
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum(SIZE);
int difference;
//If the first polynomial is larger
if (SIZE > other.SIZE)
{
difference = SIZE - other.SIZE;
for(int i = 0; i<SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = polyPtr[i];
else
{
sum.polyPtr[i] = polyPtr[i] +
other.polyPtr[i - difference];
}
}
}
//If the second polynomial is larger **PROBLEM***************************************
if(other.SIZE > SIZE)
{
difference = other.SIZE - SIZE;
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference];
}
}
}
//If the polynomials are equal
if(SIZE == other.SIZE)
{
for(int i = SIZE-1; i >= 0; i--)
{
sum.polyPtr[i] = polyPtr[i] + other.polyPtr[i];
}
}
return sum;
};
int main()
{
int polySize;
//User enters a size for the first & second polynomial
cout << "Enter a size for the first polynomial: ";
cin >> polySize;
Polynomial pOne(polySize);
cout << "\nEnter a size for the second polynomial: ";
cin >> polySize;
Polynomial pTwo(polySize);
//User enters in values (Overload of >> operator
cout << "\n\nEnter in values for the first polynomial, "<< "in the format - (x x x x): " << endl;
cin >> pOne;
cout << "\nEnter in values for the second polynomial, "<< "in the format - (x x x x): " << endl;
cin >> pTwo;
//Overload << operator for output
cout << "\nPolynomial 1 is: " << pOne << endl
<< "Polynomial 2 is: " << pTwo << endl;
Polynomial pThree = pOne + pTwo;
cout << "\nAfter being added together, the new polynomial is: "<< pThree << endl;
system("pause");
}
Окно вывода:
SIZE
из sum
должен быть максимум SIZE
из двух полиномов:
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum( max(SIZE,other.SIZE) );
В противном случае ваш новый полином будет таким же большим, как полином, над которым вы выполняете операцию, и вы будете записывать в нераспределенную память дальше по циклу:
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference]; // i may be higher than SIZE, thus sum.polyPtr[i] invokes undefined behaviour.
}
}
Текущая первая проблема здесь:
Polynomial sum(SIZE);
Лучше:
Polynomial sum(std::max(SIZE, other.SIZE));
Но я думаю, что реальная проблема заключается в том, что вам нужно упростить свой дизайн.
Первое, что можно использовать:
private:
int SIZE;
double *coef;
};
Просто сохраните коэффициент для ax ^ n в coef[n]=a
, Теперь попытайтесь выяснить, что нужно добавить.
Но гораздо проще было бы использовать
std::map<int,double> p;
хранить все. p[n]=a;
Без отладки и оптимизации, просто идея:
private:
std::map<int,double> p;
};
И забыть о любом new
, delete
и индекс вне диапазона.
+ () Будет выглядеть так:
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum; // No SIZE more.
sum.p= p;
for (auto ax_n : other.p)
sum.p[ax_n.first] += ax_n.second;
return sum;
}
Ваша проблема заключается в построении суммы (РАЗМЕР)
Polynomial Polynomial::operator+(const Polynomial& other)
{
Polynomial sum(SIZE);
Если вы сделаете это, и первый многочлен будет иметь размер только 2, позже в методе, который вы копируете в память, которая не принадлежит вам:
if(other.SIZE > SIZE)
{
difference = other.SIZE - SIZE;
//// ЗДЕСЬ ВАША ПРОБЛЕМА — ваш цикл использует other.SIZE, который больше, чем SIZE …
for(int i = 0; i<other.SIZE; i++)
{
if(i - difference < 0)
sum.polyPtr[i] = other.polyPtr[i];
else
{
sum.polyPtr[i] = other.polyPtr[i] +
polyPtr[i - difference];
}
}
}
Ошибка происходит потому, что вы используете sum.polyPtr[i]
, который, когда размер < other.SIZE происходит, не существует.
Ваш код слишком сложен. Нечто подобное делает это красиво:
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
// helper to read the input polynomials into a output-iterator
template<class OutIter>
void read_vector(std::istream& is, OutIter first)
{
// helper type to iterate over the input coefficients
typedef std::istream_iterator<
typename OutIter::container_type::value_type> iter_t;
// buffer to hold the input line
std::string buffer;
// read it
std::getline(is, buffer);
// create a string stream with which we tokenize the input
std::istringstream iss(buffer);
// read coefficients into output container
std::copy(iter_t(iss), iter_t(), first);
}
int main()
{
std::vector<double> p1, p2;
// read input
std::cout << "Enter coefficients of the first polynomial: ";
read_vector(std::cin, std::back_inserter(p1));
std::cout << "Enter coefficients of the second polynomial: ";
read_vector(std::cin, std::back_inserter(p2));
// check for errors
if (p1.empty() || p2.empty())
{
std::cerr << "Error: polynomials must not be empty\n";
return 1;
}
// initialize result polynomial to 0. coefficients
std::vector<double> p3(std::max(p1.size(), p2.size()), 0.);
// copy first polynomial to the result, starting from the back
std::copy(p1.rbegin(), p1.rend(), p3.rbegin());
// add second polynomial, starting from the back
std::transform(p2.rbegin(), p2.rend(), p3.rbegin(), p3.rbegin(),
std::plus<double>());
// print result
std::cout << "Sum: ";
const size_t n = p3.size()-1;
for (size_t i=0; i < n; ++i)
{
std::cout << std::showpos << p3[i] << "x^" << n-i;
}
std::cout << std::showpos << p3[n] << "\n";
}