How to fix segmentation fault for C++? - c++

I am getting a segmentation fault error when compiling my code. I don't know how to fix it. I am supposed to compile my Polynomial.cpp with my professor's poly_check.o, but I get a segmentation fault error.
This is my Polynomial.h:
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
using namespace std;
class Polynomial {
private:
double *coefficients;
int size;
public:
Polynomial();
Polynomial(double c[], int size);
Polynomial(const Polynomial &poly);
~Polynomial();
void set(double c[], int size);
inline int getDegree() const {
return size - 1;
}
double f(double x)const;
bool operator== (const Polynomial &poly)const;
Polynomial operator+ (const Polynomial &poly)const;
friend ostream & operator << (ostream &out, const
Polynomial &poly);
friend istream & operator >> (istream &in, Polynomial
&poly);
};
#endif
This is my Polynomial.cpp:
#include "Polynomial.h"
#include <iostream>
#include <cmath>
using namespace std;
Polynomial::Polynomial() {
size = 0;
coefficients = NULL;
}
Polynomial::Polynomial(double c[], int size) {
this->size = size;
coefficients = new double[size];
for (int i = 0; i < size; i++) {
coefficients[i] = c[i];
}
}
Polynomial::Polynomial(const Polynomial &poly) {
if (coefficients != NULL)
delete coefficients;
this->size = poly.size;
coefficients = new double[size];
for (int i = 0; i < size; i++)
coefficients[i] = poly.coefficients[i];
}
Polynomial::~Polynomial() {
if (coefficients != NULL)
delete coefficients;
}
void Polynomial::set(double c[], int size) {
this->size = size;
if (coefficients != NULL)
delete coefficients;
coefficients = new double[size];
for (int i = 0; i < size; i++)
coefficients[i] = c[i];
}
double Polynomial::f(double x)const {
double value = 0.0;
for (int i = 0; i < size; i++) {
value += (coefficients[i] * pow(x, i));
}
return value;
}
bool Polynomial::operator== (const Polynomial &poly)const {
if (this->size != poly.size)
return false;
for (int i = 0; i < size; i++) {
if (poly.coefficients[i] != coefficients[i])
return false;
}
return true;
}
Polynomial Polynomial::operator+ (const Polynomial &poly)const {
int maxSize = size;
if (poly.size > maxSize)
maxSize = poly.size;
double sum[maxSize] = {0.0};
for (int i = 0; i < size; i++) {
sum[i] = coefficients[i];
}
for (int i = 0; i < poly.size; i++) {
sum[i] += poly.coefficients[i];
}
Polynomial sumP(sum, maxSize);
return sumP;
}
ostream &operator << (ostream &out, const Polynomial &poly) {
for (int i = poly.size - 1; i >= 0; i--) {
if (i != poly.size - 1) {
if (poly.coefficients[i] >= 0)
out << " + ";
else
out << " - ";
}
out << poly.coefficients[i];
if (i == 0)
continue;
if (i == 1)
out << "x";
else
out << "x^" << i;
}
return out;
}
istream &operator >> (istream &in, Polynomial &poly) {
int degree;
in >> degree;
double c[100];
int size = 0;
while (in >> c[size]) {
size++;
if ((size-1) == degree)
break;
}
poly.set(c, size);
return in;
}
This is my poly_test.cpp:
#include "Polynomial.h"
#include <iostream>
using namespace std;
int main(void) {
double c1[] = {0, 1, 2, 3, 4};
double c2[] = {0, 1, 2, 3, 4, 5, 6};
Polynomial p1(c1, 5);
Polynomial p2(c2, 7);
Polynomial p3;
cout << "Enter p3: ";
cin >> p3;
cout << "p1: ";
cout << p1 << endl;
cout << "p2: ";
cout << p2 << endl;
cout << "p3: ";
cout << p3 << endl;
Polynomial p4;
p4 = p1 + p2;
cout << "p4 = p1 + p2, p4: ";
cout << p4 << endl;
double value = p1.f(2);
cout << "Evaluating p1 at x = 2, p1 = ";
cout << value << endl;
Polynomial p6(c1, 5);
cout << "p6: ";
cout << p6 << endl;
if (p6 == p1) {
cout << "p6 and p1 are equal. Equality test passed" <<
endl;
}
else {
cout << "Equality test failed" << endl;
}
return 0;
}
This is the error that I am getting:
segmentation fault error

In general, you should test your own code as you develop it. Don't write this much code and then plug it into a test function; it will fail, and the process of debugging it will be long and discouraging.
The specific problem (or one of them) is that you neglected to implement operator=. Are you familiar with shallow copies and deep copies? The default copy constructor is a shallow copier, so that two instances of Polynomial wind up with pointers to the same array. Then when they die, they both try to delete it.

Related

How to properly implement a copy constructor for a dynamic Matrix?

I have a Matrix (Matriz) class implemented as following:
Header:
#ifndef MATRIZ_H
#define MATRIZ_H
class Matriz
{
public:
Matriz(unsigned int nL, unsigned int nC);
~Matriz();
Matriz& operator+=(const Matriz &ptr);
const Matriz operator+(const Matriz &ptr) const;
Matriz* subtracaoMatriz(Matriz *m);
Matriz* multiplicacaoMatriz(Matriz *m);
void inserirMatriz();
void imprimirMatriz();
int verificaOperacao(const Matriz& ptr);
Matriz& operator-=(const Matriz &ptr);
const Matriz operator-(const Matriz &ptr) const;
const Matriz operator*(const Matriz &ptr) const;
protected:
private:
unsigned int nLinhas;
unsigned int nColunas;
int** matrix;
int verificaOperacao(Matriz *m); //0 -> cannot make the operation; 1 -> OK for product; 2 -> OK for sum;
};
#endif // MATRIZ_H
Implementation:
#include "Matriz.h"
#include <iostream>
using namespace std;
Matriz::Matriz(unsigned int nL, unsigned int nC)
{
this->nLinhas = nL;
this->nColunas = nC;
this->matrix = new int*[nLinhas];
for (unsigned int i = 0; i < nLinhas; ++i)
this->matrix[i] = new int[nColunas];
for(unsigned int i = 0; i < nLinhas; i++)
for(unsigned int j = 0; j < nColunas; j++)
this->matrix[i][j] = 0;
}
Matriz::~Matriz()
{
//dtor
}
int Matriz::verificaOperacao(Matriz *m)
{
if((this->nLinhas == m->nLinhas) && (this->nColunas == m->nColunas))
return 2;
else if(this->nColunas == m->nLinhas)
return 1;
else
return 0;
}
int Matriz::verificaOperacao(const Matriz& ptr)
{
if((this->nLinhas == ptr.nLinhas) && (this->nColunas == ptr.nColunas))
return 2;
else if(this->nColunas == ptr.nLinhas)
return 1;
else
return 0;
}
Matriz& Matriz::operator+=(const Matriz &ptr) {
if(this->verificaOperacao(ptr) == 2)
{
for(unsigned int i = 0; i < this->nLinhas; i++)
for(unsigned int j = 0; j < this->nColunas; j++)
this->matrix[i][j] = this->matrix[i][j] + ptr.matrix[i][j];
return *this;
}
else
return *this;
}
const Matriz Matriz::operator+(const Matriz &ptr) const {
Matriz resultado = *this;
resultado += ptr;
return resultado;
}
Matriz& Matriz::operator-=(const Matriz &ptr) {
if(this->verificaOperacao(ptr) == 2)
{
for(unsigned int i = 0; i < this->nLinhas; i++)
for(unsigned int j = 0; j < this->nColunas; j++)
this->matrix[i][j] = this->matrix[i][j] - ptr.matrix[i][j];
return *this;
}
else
return *this;
}
const Matriz Matriz::operator-(const Matriz &ptr) const {
Matriz resultado = *this;
resultado -= ptr;
return resultado;
}
const Matriz Matriz::operator*(const Matriz &ptr) const {
Matriz *resultado = new Matriz(this->nLinhas, ptr.nColunas);
for(unsigned i = 0; i < this->nLinhas; i++)
{
for(unsigned j = 0; j < ptr.nColunas; j++)
for(unsigned int aux = 0; aux < ptr.nColunas; aux++)
resultado->matrix[i][j] += this->matrix[i][aux] * ptr.matrix[aux][j];
}
return *resultado;
}
void Matriz::inserirMatriz()
{
for(unsigned int i = 0; i < this->nLinhas; i++)
for(unsigned int j = 0; j < this->nColunas; j++)
cin >> this->matrix[i][j];
}
void Matriz::imprimirMatriz()
{
for(unsigned int i = 0; i < this->nLinhas; i++) {
for(unsigned int j = 0; j < this->nColunas; j++)
cout << this->matrix[i][j] << "\t";
cout << endl;
}
}
Main:
#include <iostream>
#include "Matriz.h"
using namespace std;
int main()
{
Matriz *m1 = new Matriz(2, 2);
Matriz *m2 = new Matriz(2, 2);
m1->inserirMatriz();
m2->inserirMatriz();
cout << "Matrix 1:" << endl;
m1->imprimirMatriz();
cout << "Matrix 2:" << endl;
m2->imprimirMatriz();
Matriz m3 = *m1 + *m2;
cout << "The sum is: " << endl;
m3.imprimirMatriz();
cout << "The subtraction is: " << endl;
Matriz m4 = *m1 - *m2;
m4.imprimirMatriz();
cout << "The product is: " << endl;
Matriz m5 = *m1 * *m2;
m5.imprimirMatriz();
///HERE LIES THE PROBLEM
m2 = m1;
cout << "m2 = m1" << endl;
cout << "m2:" << endl;
m2->imprimirMatriz();
cout << "*m1 += *m2" << endl;
cout << "m2:" << endl;
*m1 += *m2;
m2->imprimirMatriz();
delete m1;
delete m2;
return 0;
}
I believe that the issue is caused by the default copy constructor, however I tried without success to implement one.
There are two ways to implement a copy constructor:
Method 1
Use a std::vector instead of dynamic memory, this approach eliminates the need for a custom copy constructor and removes the risk of memory leaks, see here. I'm not going to rewrite your code but do some simple stuff to illustrate the point:
// Header file
#include <vector>
class Matriz
{
...
private:
std::vector<std::vector<int>> matrix;
}
// CPP file
Matriz::Matriz(unsigned int nL, unsigned int nC)
{
matrix.resize(nL, std::vector<int>(nC, 0));
// You can now access items with matrix[x][y].
}
This method with vectors works because when you want to copy your Matriz class the copy constructors for the vector will automatically be called. It's all done for you.
Method 2
If you still want to use dynamic memory then you need to implement a deep copy constructor:
//Header file.
class Matriz
{
...
Matriz(const Matriz& m);
}
// CPP file
Matriz::~Matriz() { delete[] matrix; } // DO NOT FORGET THIS!!!
Matriz::Matriz(const Matriz& m)
{
delete[] matrix;
// Create the dynamic memory.
int** matrix = new int*[m.nLinhas];
for(int i = 0; i < m.nLinhas; ++i)
matrix[i] = new int[nColunas];
nLinhas = m.nLinhas;
nColunas = m.Colunas;
// Copy over the data.
for(int l = 0; l < nLinhas; l++)
{
for(int c = 0; c < nColunas; c++)
{
matrix[l][c] = m.matrix[l][c];
}
}
}
You can follow the same concepts for the assignment operator operator=. I would suggest using the vector if you can, this will eliminate any possible leak issues and given what you are doing there won't be any speed loss issues.

Delete[] array breaks my C++ program

I have had this issue for a while now. Every time my grow function calls the delete line, the program breaks. It doesn't give me an error besides it has reached a break point. I have not found a solution to this online during my Google searches. Can anyone help?
UPDATE After hitting continue on the error screen a few times if finally came up with a different error. It states that CrtIsValidHeapPointer(pUserData)
Driver.cpp
#include <iostream>
#include "MyVector.h"
using namespace std;
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);
int main()
{
cout << "\nCreating a vector Sam of size 4.";
MyVector sam(4);
cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nCreating a vector Joe of size 4.";
MyVector joe(4);
cout << "\nPush 6 values into the vector.";
for (int i = 0; i < 6; i++)
joe.push_back(i * 3);
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
cout << "\nTest the overloaded assignment operator \"joe = sam\": ";
joe = sam;
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
// pass a copy of sam by value
printV(sam);
cout << endl;
system("PAUSE");
return 0;
}
void printV(MyVector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
My Vector.h
#include <iostream>
#include <ostream>
using namespace std;
#pragma once
class MyVector
{
private:
int vSize;
int vCapacity;
int* vArray;
void grow();
public:
MyVector();
MyVector(int n);
MyVector(const MyVector& b);
int size() const;
int capacity() const;
void clear();
void push_back(int n);
int& at(int n) const;
MyVector& operator=(const MyVector& rho);
~MyVector();
};
ostream& operator<<(ostream& out, const MyVector& rho);
MyVector.cpp
#include "MyVector.h"
#include <iostream>
#include <ostream>
using namespace std;
MyVector::MyVector()
{
vArray = nullptr;
vSize = 0;
vCapacity = 0;
}
MyVector::MyVector(int n)
{
vArray = new int[vCapacity];
vSize = 0;
vCapacity = n;
}
MyVector::MyVector(const MyVector& b)
{
vSize = b.size();
vArray = new int[vSize];
for (int i = 0; i < b.size(); i++)
{
this->vArray[i] = b.vArray[i];
}
}
int MyVector::size() const
{
return vSize;
}
int MyVector::capacity() const
{
return vCapacity;
}
void MyVector::clear(void)
{
if (vArray != nullptr)
{
delete[] vArray;
vArray = nullptr;
vSize = 0;
vCapacity = 0;
}
}
void MyVector::push_back(int n)
{
if (vCapacity == 0)
{
vCapacity++;
int* tmp = new int[vCapacity];
delete[] vArray;
vArray = tmp;
}
if (vSize >= vCapacity)
{
grow();
}
vArray[vSize] = n;
vSize++;
}
void MyVector::grow()
{
vCapacity = vCapacity + vCapacity;
int* tmp = new int[vCapacity];
for (int i = 0; i < vSize+1; i++)
{
tmp[i] = vArray[i];
}
delete[] vArray;
vArray = tmp;
}
int& MyVector::at(int index) const
{
if (index >= 0 && index<vSize)
{
return vArray[index];
}
else
{
throw index;
}
}
MyVector& MyVector::operator=(const MyVector& rho)
{
// test for self assignment
if (this == &rho)
return *this;
// clean up array in left hand object (this)
delete[] this->vArray;
// create a new array big enough to hold right hand object's data
vSize = rho.size();
this->vArray = new int[vSize];
// copy the data
for (int i = 0; i < rho.size(); i++)
{
this->vArray[i] = rho.vArray[i];
}
// return this object
return *this;
}
MyVector::~MyVector()
{
if (vArray != nullptr)
{
clear();
}
}
ostream& operator<< (ostream& out, const MyVector& rho)
{
for (int i = 0; i < rho.size(); i++)
{
out << rho.at(i);
}
return out;
}
Your problem is your constructor that takes a parameter:
MyVector::MyVector(int n)
{
vArray = new int[vCapacity];
vSize = 0;
vCapacity = n;
}
You are using vCapacity before you assign it a value. This can lead to an attempt to allocate a large or not large enough block of data.

C++ class Matrix, crash

I got here class Matrix, the problem is that it crashes after one line of code: e.g Matrix A(2,2);
So it's most likely constructor, but the thing is that when I copied my constructor into other class Matrix it worked just fine... I think I am blind
#include<iostream>
#include<cmath>
#include<string>
#include<fstream>
using namespace std;
class Matrix
{
public:
Matrix(int, int);
Matrix(const Matrix& copyMatrix);
~Matrix();
//Matrix(const char *sciezka);
Matrix& mac_cin(string);
friend ostream& operator<< (ostream&, Matrix&);
Matrix& operator+= (const Matrix&);
Matrix& operator-= (const Matrix&);
Matrix& operator*= (const Matrix&);
Matrix& operator= (const Matrix&);
friend Matrix operator* (const Matrix & left, const Matrix & right);
friend Matrix operator+ (const Matrix & left, const Matrix & right);
friend Matrix operator- (const Matrix & left, const Matrix & right);
class RangeError{};
class AllocError{};
class OpenError{};
class IncorrectSize{};
private:
double **macierz;
unsigned int wiersze, kolumny;
};
Matrix::Matrix(int x = 1, int y = 1): wiersze(x), kolumny(y)
{
if (wiersze < 1 || kolumny < 1)
{
throw AllocError();
}
macierz = new double*[wiersze];
for (unsigned i = 0; i < wiersze; i++)
{
macierz[i] = new double[kolumny];
for (unsigned j = 0; j < kolumny; j++)
{
macierz[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& copyMatrix)
{
wiersze=copyMatrix.wiersze;
kolumny=copyMatrix.kolumny;
macierz = new double*[wiersze];
for (unsigned i = 0; i < wiersze; i++)
{
macierz[i] = new double[kolumny];
for (unsigned j = 0; j < kolumny; j++)
{
macierz[i][j] = copyMatrix.macierz[i][j];
}
}
}
Matrix::~Matrix()
{
delete [] macierz;
for (unsigned i = 0; i < wiersze; i++)
{
delete [] macierz[i];
}
}
/*
Matrix::Matrix(const char *sciezka)
{
ifstream plik(sciezka);
if (plik.good() != true)
{
throw OpenError();
}
plik >> wiersze >> kolumny;
macierz = new double*[wiersze];
for (unsigned i = 0; i < wiersze; i++)
{
for (unsigned j = 0; j < kolumny; j++)
{
plik >> macierz[i][j];
}
}
//delete [] *macierz;
//delete [] macierz;
}
*/
ostream & operator<< (ostream& wyjscie, Matrix& co)
{
for (unsigned i = 0; i < co.wiersze; i++)
{
for (unsigned j = 0; j < co.kolumny; j++)
{
wyjscie << co.macierz[i][j] << " ";
}
cout << endl;
}
}
Matrix operator* (const Matrix & left, const Matrix & right)
{
Matrix nlr(left);
return nlr *= right;
}
Matrix operator+ (const Matrix & left, const Matrix & right)
{
Matrix nlr(left);
return nlr += right;
}
Matrix operator- (const Matrix & left, const Matrix & right)
{
Matrix nlr(left);
return nlr -= right;
}
Matrix& Matrix::operator+=(const Matrix& co)
{
if(this->wiersze!=co.wiersze || this->kolumny!=co.kolumny)
{
throw IncorrectSize{};
}
for(unsigned i=0; i<this->wiersze; i++)
{
for(unsigned j=0; j<this->kolumny; j++)
{
this->macierz[i][j] = this->macierz[i][j]+co.macierz[i][j];
}
}
return *this;
}
Matrix& Matrix::operator-=(const Matrix& co)
{
if(this->wiersze!=co.wiersze || this->kolumny!=co.kolumny)
{
throw IncorrectSize{};
}
for(unsigned i=0; i<this->wiersze; i++)
{
for(unsigned j=0; j<this->kolumny; j++)
{
this->macierz[i][j] = this->macierz[i][j]-co.macierz[i][j];
}
}
return *this;
}
Matrix& Matrix::operator*=(const Matrix& co)
{
if(this->wiersze!=co.wiersze || this->kolumny!=co.kolumny)
{
throw IncorrectSize{};
}
for(unsigned i=0; i<this->wiersze; i++)
{ // moze double temp=0;
for(unsigned j=0; j<this->kolumny; j++)
{
this->macierz[i][j] = this->macierz[i][j]*co.macierz[i][j]; // temp+=
}
} // moze newMatrix.macierz[i][j] = temp;
return *this;
}
Matrix& Matrix::operator=(const Matrix& co)
{
if(this->wiersze!=co.wiersze || this->kolumny!=co.kolumny)
{
throw IncorrectSize{};
}
for(unsigned i=0; i<this->wiersze; i++)
{
for(unsigned j=0; j<this->kolumny; j++)
{
this->macierz[i][j] = co.macierz[i][j];
}
}
return *this;
}
Matrix& Matrix::mac_cin(string mac) {
int i,j;
cout << "Podaj zawartosc macierzy\n";
for(i=0; i<this->wiersze; i++)
{
for(j=0; j<this->kolumny; j++)
{
cout << mac << "[" << i << "][" << j << "] = ";
cin >> this->macierz[i][j];
}
}
return *this;
}
int main()
{
Matrix A(2,2);
A.mac_cin("A");
Matrix okA(A);
return 0;
}
When I use TDM-GGC 32 Bit it works BUT when I change main to:
int main()
{
Matrix A(2,2);
A.mac_cin("A");
Matrix okA(A);
Matrix B(3,3);
B.mac_cin("B");
Matrix okB(B);
Matrix C(3,3);
Matrix okC(C);
cout << endl;
cout << "A: " << endl << A << endl << endl;
cout << "B: " << endl << B << endl << endl;
C=A+B;
cout << "A+B: " << endl << C << endl << endl;
C=A-B;
cout << "A-B: " << endl << C << endl << endl;
C=A*B;
cout << "A*B: " << endl << C << endl << endl;
C=A;
C+=B;
cout << "A+=B: " << endl << C << endl << endl;
C=A;
C-=B;
cout << "A-=B: " << endl << C << endl << endl;
C=A;
C*=B;
cout << "A*=B: " << endl << C << endl << endl;
system("PAUSE");
return 0;
}
then it's not working again (and it works on similar matrix with my constructors...)
The overloaded operator << should return the ostream object i.e.wyjscie, this enables chaining while using the cout << A << ..., etc.
This is where your code is crashing, so fix as follows :
ostream & operator<< (ostream& wyjscie, Matrix& co)
{
//...
wyjscie << endl;
return wyjscie ; // <---- Notice this
}
Note : There might be other errors too
I'm not sure if this is the source of your problem, but in the destructor you are deleting macierz right before iterating over it and accessing elements. You should iterate over it first, and delete the whole thing afterwards.

Operator overloading unhandled exception

I am having some trouble overloading the + operator. I get a runtime error. Unhandled exception followed by a memory address.
Below is what I have coded:
#include <iostream>
#include <iomanip>
using namespace std;
class myVector{
int vsize, maxsize;
int* array;
void alloc_new();
friend ostream& operator<< (ostream &out, myVector&);
friend istream& operator>> (istream &in, myVector&);
public:
myVector();
myVector(int);
myVector(const myVector&); //copy constructor
~myVector();
void push_back(int);
int size();
int operator[](int);
myVector operator+(myVector&);
int at(int i);
};
myVector::myVector()
{
maxsize = 20;
array = new int[maxsize];
vsize = 0;
}
myVector::myVector(int i)
{
maxsize = i;
array = new int[maxsize];
vsize = 0;
}
myVector::myVector(const myVector& v){}
myVector::~myVector()
{
delete[] array;
}
void myVector::push_back(int i)
{
if (vsize + 1 > maxsize)
alloc_new();
array[vsize] = i;
vsize++;
}
int myVector::operator[](int i)
{
return array[i];
}
int myVector::at(int i)
{
if (i < vsize)
return array[i];
throw 10;
}
void myVector::alloc_new()
{
maxsize = vsize * 2;
int* tmp = new int[maxsize];
for (int i = 0; i < vsize; i++)
tmp[i] = array[i];
delete[] array;
array = tmp;
}
int myVector::size()
{
return vsize;
}
myVector myVector::operator+(myVector& a)
{
myVector result;
for (int i = 0; i < a.size(); i++)
result.array[i] = this->array[i] + a.array[i];
return result;
}
ostream& operator<< (ostream &out, myVector& a)
{
for (int i = 0; i < a.size(); i++)
out << a[i] << " ";
return out;
}
istream& operator>> (istream &in, myVector& a)
{
int tmp, lol;
cin >> tmp;
for (int i = 0; i < tmp; i++)
{
cin >> lol;
a.push_back(lol);
}
return in;
}
int main()
{
myVector vec;
myVector vec2;
myVector c;
int width = 15;
cout << "Input vector a\n";
cin >> vec; // In: 3 1 2 3
cout << "Input vector b\n";
cin >> vec2; // In: 3 4 5 6
cout << setw(width) << "Vector a: " << vec << endl;
cout << setw(width) << "Vector b: " << vec2 << endl;
cout << setw(width) << "c = a + b: " << c << endl;
c = vec + vec2;
system("PAUSE");
return 0;
}
How would I go about writing a copy constructor for a dynamic array? This is what I have right now:
myVector::myVector(const myVector &initial)
{
int* tmp = new int[3];
for (int i = 0; i < 3; i++)
tmp[i] = initial.array[i];
delete[] array;
array = tmp;
}
When you're assigning the results in your operator+, you've done nothing to reserve space in the results vector.
(You should slather your class in runtime checks (assert or similar) to sanity-check all the inputs to every method. That would show you that your result indexer passed in an index which didn't exist in the vector.)

Polynomial Operations [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am trying to write a program that constructs a polynomial from an input file. It reads in the polynomial and stores values into the class attributes "coefficient" and "exponent". E.g. coefficient = 2, exponent = 3 would result in 2x^3. There are a lot of annoying corner cases that must be handled when reading in the polynomial and outputting. (operator<< and operator>> functions) My main function thoroughly tests my polynomial.cpp. I believe one of my problems is coming from constructing the polynomial and as you may note, I'm also having trouble writing code for my derive function. Here is what I have:
#ifndef _POLYNOMIAL_H
#define _POLYNOMIAL_H
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
class Polynomial {
public:
Polynomial();
Polynomial(vector<double> iCoefficients, vector<int> iExponents);
int Degree() const;
double Evaluate(double x) const;
Polynomial Derivative() const;
friend Polynomial operator+(const Polynomial & p, const Polynomial & p2);
friend Polynomial operator*(const Polynomial & p, const Polynomial & p2);
friend ostream& operator<<(ostream& out, const Polynomial & p);
friend istream& operator>>(istream& in, Polynomial & p);
private:
vector<double> coefficients;
};
#endif
#include "polynomial.h"
#include <stdexcept>
#include <vector>
#include <cmath>
using namespace std;
// Default Constructor
Polynomial::Polynomial() {
coefficients.push_back(0);
}
// Constructor for a Polynomial
Polynomial::Polynomial(vector<double> iCoefficients, vector<int> iExponents) {
for (int i = 0; i < iExponents[0]; i++) {
coefficients.push_back(0);
}
for (size_t i = 0; i < iExponents.size(); i++) {
coefficients[(Degree() - iExponents[i])] = iCoefficients[i];
}
}
// Returns highest exponent of the polynomial
int Polynomial::Degree() const {
return coefficients.size();
}
// Evaluates the polynomial at a particular point
double Polynomial::Evaluate(double x) const {
double result;
for(int i = 0; i <= Degree(); i++) {
result += pow(x, Degree() - i) * coefficients[i];
}
return result;
}
// Returns first derivative of the polynomial
Polynomial Polynomial::Derivative() const { //----------------------???
// Polynomial result;
// for(int i = 0; i <= Degree(); i++) {
// result.coefficients[i] = coefficients[i] * (Degree() - i);
// }
// return result;
}
// Returns polynomial object that is the sum of parameters
Polynomial operator+(const Polynomial & p, const Polynomial & p2) {
int d = p.Degree();
int d2 = p2.Degree();
Polynomial sum;
for (int j = 0; j < d; j++) {
for (int i = 0; i < d2; i ++) {
sum.coefficients.push_back(p.coefficients[j] + p2.coefficients[i]);
}
}
return sum;
}
// Returns polynomial object that is the product of parameters
Polynomial operator*(const Polynomial & p, const Polynomial & p2) {
int d = p.Degree();
int d2 = p2.Degree();
Polynomial product;
for (int j = 0; j < d; j++) {
for (int i = 0; i < d2; i ++) {
product.coefficients.push_back(p.coefficients[j] * p2.coefficients[i]);
}
}
return product;
}
// Output operator
ostream& operator<<(ostream& out, const Polynomial & p) {
for (int i = 0; i <= p.Degree(); i++) {
if(i == 0 && p.Degree() <= 1) {
out << 0;
}
if (p.coefficients[i] != 0 && i != 0) {
out << '+';
}
if (p.coefficients[i] != 0) {
out << p.coefficients[i];
if(i < (p.Degree() - 1)) {
out << "x^";
out << (i - p.Degree()) * (-1);
}
}
}
return out;
}
// Input operator
istream& operator>>(istream& in, Polynomial & p) {
char ch;
int exponent;
double coefficient;
vector<double> coefficients;
vector<int> exponents;
while(isspace(ch) == false) {
ch = in.peek();
if(ch == '+') {
in.ignore();
in >> coefficient;
}
else if(ch == '-') {
in.ignore();
in >> coefficient;
coefficient = coefficient * (-1);
}
else {
in >> coefficient;
}
ch = in.peek();
if((ch <= 'z') && (ch >= 'a')) {
in >> ch;
ch = in.peek();
if(ch == '^') {
in.ignore();
in >> exponent;
}
else
exponent = 1;
}
else
exponent = 0;
coefficients.push_back(coefficient);
exponents.push_back(exponent);
}
p = Polynomial(coefficients, exponents);
return in;
}
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
#include "polynomial.h"
using namespace std;
bool testPolynomial(const Polynomial& p, string expected);
bool testOperations(const Polynomial& p, int degree, double expected);
bool testInput(string s);
int main() {
int errors = 0;
cerr << "Note: Nearly all of the tests expect a working output operator. If a test fails, check that first" << endl;
cerr << "Testing default constructor" << endl;
Polynomial p1; // test default constructor
errors += testPolynomial(p1, "0");
cerr << "Testing explicit value constructor" << endl;
double c_arr[] = {1.1, 2, 4, 7};
int e_arr[] = {6, 3, 2, 0};
vector<double> c(c_arr, c_arr+4);
vector<int> e(e_arr, e_arr+4);
Polynomial p2(c, e);
errors += testPolynomial(p2, "1.1x^6+2x^3+4x^2+7");
c.clear(); e.clear();
cout << '1' << endl;
Polynomial p3(c, e);
errors += testPolynomial(p3, "0");
cout << '2' << endl;
cerr << "Testing operations" << endl;
double c2_arr[] = {-1.1, 2, -4, 7};
int e2_arr[] = {4, 3, 2, 0};
vector<double> c2(c2_arr, c2_arr+4);
vector<int> e2(e2_arr, e2_arr+4);
Polynomial p4(c2,e2);
errors += testOperations(p1, 0, 0);
errors += testOperations(p2, 6, 109.4);
errors += testOperations(p4, 4, -10.6);
errors += testPolynomial(p1.Derivative(), "0");
errors += testPolynomial(p2.Derivative(), "6.6x^5+6x^2+8x");
errors += testPolynomial(p4.Derivative(), "-4.4x^3+6x^2-8x");
errors += testPolynomial(p1+p2, "1.1x^6+2x^3+4x^2+7");
errors += testPolynomial(p2+p4, "1.1x^6-1.1x^4+4x^3+14");
errors += testPolynomial(p1*p2, "0");
errors += testPolynomial(p2*p2, "1.21x^12+4.4x^9+8.8x^8+19.4x^6+16x^5+16x^4+28x^3+56x^2+49");
double c_arr3[] = {-1};
int e_arr3[] = {0};
vector<double> c3 = vector<double>(c_arr3, c_arr3+1);
vector<int> e3 = vector<int>(e_arr3, e_arr3+1);
Polynomial p5(c3, e3);
errors += testPolynomial(p2 * p5 + p2, "0");
errors += testPolynomial(p5, "-1");
cerr << "Testing input operator." << endl;
testInput("0");
testInput("51");
testInput("-1.1");
testInput("3x^2");
testInput("-5x^3-5");
testInput("x^5+x-1");
testInput("-x^4+2");
return errors;
}
bool testPolynomial(const Polynomial& p, string expected) {
ostringstream out;
out << p;
if (out.str() != expected) {
cerr << "Test failed: expected " << expected << " got " << out.str() << endl;
return true;
} else {
return false;
}
}
bool testOperations(const Polynomial& p, int degree, double expected) {
if(p.Degree() != degree) {
cerr << "Failed Degree operation" << endl;
return true;
}
double result = p.Evaluate(2.0);
if (fabs(result - expected) > 1e-5) {
cerr << "Failed Evaluation operation" << endl;
}
return false;
}
bool testInput(string s) {
Polynomial p;
istringstream in(s+" ");
in >> p;
ostringstream out;
out << p;
if (out.str() != s) {
cerr << "Failed input test. Expected: " << s << " got " << out.str() << endl;
return true;
}
return false;
}
The Polynomial::Degree() function has an off-by-one bug; it should return size()-1
In order to convert the lists of coefficients and exponents, first find the maximal exponent; this will be the degree of the polynomial:
int degree = *std::max_element(iExponents.begin(), iExponents.end());
Then, initialize coefficients with this number of zeros (plus one, see above):
coefficients.assign(degree + 1, 0);
Then, set each coefficient, just like you did.
However, it is much better to use ascending order of powers/exponents! This way, you don't need to calculate Degree()-i all the time, you can use i instead.
for (size_t i = 0; i < iExponents.size(); i++) {
coefficients[iExponents[i]] += iCoefficients[i];
}
Note += in the code above; it handles polynomials like 3x+4x+5x, making that equivalent to 12x.
Your addition and multiplication algorithms are completely wrong. You should first set the degree of the output polynomial, just like you did in the constructor:
Polynomial operator+(const Polynomial & p, const Polynomial & p2)
{
int d = p.Degree();
int d2 = p2.Degree();
Polynomial sum;
sum.coefficients.assign(std::max(d, d2) + 1, 0);
...
}
The rest should be easier, once you try to think about it.
After performing the addition, you might want to check for zero highest-degree coefficients; for example, when you add 2x^2+x+1 and -2x^2+x+1, you get 0x^2+2x+2, which you might want to convert to 2x+2:
while (coefficients.back() == 0)
coefficients.resize(coefficients.size() - 1);
if (coefficients.empty())
coefficients.push_back(0);
Derivative should be easy, once you get operator+ and operator* right.