Trouble adding two polynomials built as linked-list c++ - c++

*Note: This is for an assignment: I don't want a solution, just some hints to get me thinking in the correct direction.
I've created a linked-list of Polynomial term objects (PolyTerm). I am supposed to write opperator overloads for + and -. I've not been able to figure out a way to get the overloading done. Doing research, I believe that the way that I set up the link list that I might not be able to do the overloads. I think I should have made a struct for the Nodes and put the nodes into an class. Instead, I just set it up as a single class and now I am struggling with trying to overload with pointers (which you can't do as far as I know).
I've created an addition member function and am wondering if there is any way of using that to cludge an + operator overload? Everything I've been reading seem to indicate no, but I just want final verification.
Here is my header for my class:
class PolyTerm
{
public:
/************************** CLASS CONSTRUCTORS *********************************/
PolyTerm(); // Default constructor
PolyTerm(int constant); // Constant term constructor
PolyTerm(int newExp, int newCoeff); // Unlinked term constructor
PolyTerm(int newExp, int newCoeff,
PolyTerm* next, PolyTerm* prev); // Full constructor
PolyTerm(PolyTerm* original); // Copy Constructor
/*******************************************************************************/
/**************************** CLASS DESTRUCTOR *********************************/
~PolyTerm();
/************************** ACCESSOR FUNCTIONS *********************************/
int getCoeff() const; // Returns coefficient of this term
int getExp() const; // Returns the exponent of this term
PolyTerm* getNext() const; // Returns the address of the next term
PolyTerm* getPrev() const; // Returns the address of the previous term
/*******************************************************************************/
/*************************** MUTATOR FUNCTIONS *********************************/
void setCoeff(int newCoeff); // Sets the value of this term's coefficient
void setExp(int newExp); // Sets the value of this term's coefficient
void setNext(PolyTerm* newNext); // Sets the value of this term's next term
void setPrev(PolyTerm* newPrev); // Sets the value of this term's prev term
/*******************************************************************************/
/**************************** MEMBER FUNCTIONS *********************************/
int evalTerm(int value); // Evaluates the term for using 'value'
void printTerm(); // Prints this term. ex '4x^3'
void printPoly(); // Prints the whole polynomial
void insertTerm(PolyTerm* afterMe, int exp, int coeff); // Node insertion
PolyTerm* addTogether(PolyTerm* p2); // adds this and p2 together.
PolyTerm* subtractThis(PolyTerm* p2); // subtracts this - p2.
/*******************************************************************************/
/************************** OPERATOR OVERLOADS *********************************/
const PolyTerm& operator+(const PolyTerm &other) const; // <----Cant figure this out
protected:
/**************************** MEMBER VARIABLES *********************************/
int exp; // The exponent of this term
int coeff; // The coefficient of this term
PolyTerm *next; // The location of the next term
PolyTerm *prev; // The location of the previous term
/*******************************************************************************/
private:
};
Everything else in the class works properly. Here is the AddTogether function definition as well. It works well, just not exactly what the assignment wants.
PolyTerm* PolyTerm::addTogether(PolyTerm* p2)
{
PolyTerm* bigHead; // This pointer has an Ego Problem.
PolyTerm* big;
PolyTerm* small;
int bigDegree, smallDegree;
// Sets the bigger degree and smaller degree polynomial.
if(this->getExp() >= p2->getExp())
{
big = new PolyTerm(this);
small = p2;
}
else
{
big = new PolyTerm(p2);
small = this;
}
//Assign a head pointer for big polynomial (resultant of sums)
bigHead = big;
bigDegree = big->getExp();
smallDegree = small->getExp();
// Step through the members of the big polynomial that don't
// don't have a corresponding term in small one.
for (int i = 0; i < bigDegree - smallDegree; i++)
{
big = big->getNext();
}
// For each term that they have in common, add the coefficients
// and create a new term.
for (int i = 0; i <= smallDegree; i++)
{
big->setCoeff(big->getCoeff() + small->getCoeff());
big = big->getNext();
small = small->getNext();
}
return bigHead;
}
Am I right that I can't set up an operator overload for this class?

Hope this will give some idea
class Test
{
public:
int x;
Test(int val)
{
x = val;
}
Test()
{
x = 0;
}
Test* operator+(const Test& testRhs)const
{
Test* test = new Test();
test->x = this->x + testRhs.x;
return test;
}
Test* operator+(const Test* testRhs)const
{
Test* test = new Test();
test->x = this->x + testRhs->x;
return test;
}
};
using namespace std;
int main()
{
Test* pTestOut = NULL;
Test test0(5);
Test test1(3);
pTestOut = test0 + test1; //calling Test* operator+(Test& testRhs)const
cout << pTestOut->x << endl;
Test* pTestOut2 = NULL;
Test* pTest3 = new Test(2);
Test* pTest4 = new Test(8);
pTestOut2 = (*pTest3) + pTest4; //Calling Test* operator+(Test* testRhs)const
//First parameter should be object reference. So looks ugly
cout << pTestOut2->x << endl;
return 0;
}
Please refer Operator overloading : cannot add two pointers for writing looking good functions

Related

How to use some class in paramater template other class?

I have two classes Polynom and Fraction.
I need to do a template for Polynom, for using Fraction like coefficient in Polynom, like: 3/4 x^0 + 5\6 x^1 etc.
I understood how to use a simple type like double or int, but how to get this to work for a class I have no idea, and can't find a material on this theme.
class Fraction {
private:
int numerator, denominator;
public:
Fraction();
Fraction(int, int);
Fraction(int);
}
template<class T>
class PolynomT {
private:
int degree;
T *coef;
public:
PolynomT();
explicit PolynomT(int, const T * = nullptr);
~PolynomT();
};
template<class T>
PolynomT<T>::PolynomT(int n, const T *data): degree(n) {
coefA = new T[degree+1];
if (data == nullptr) {
for (int i = 0; i < degree+1; ++i)
coefA[i] = 0.0;
}
else {
for (int i = 0; i < degree + 1; ++i)
coefA[i] = data[i];
}
}
/*Problem here*/
int main() {
PolynomT<Fraction> a(); // what need to pass on here in arguments?
// how should the constructor look like?
/*Example*/
PolynomT<Fraction> b();
PolynomT<Fraction> c = a + b; // or something like this.
}
So, how to do the class constructor for Fraction in PolynomT, and how to do overloading operators for this?
The problem with the coefA[i] = 0.0 assignment in the PolynomT constructor happens because Fraction does not have a constructor that takes a double, nor does it have an assignment operator that takes a double. There are several possible solutions.
Change from raw memory management to std::vector for coefA.
std::vector<T> coefA;
// Then resize appropriately in the constructor
This would automatically fill all the elements with a default constructed object, so you wouldn't need to do anything if data == nullptr.
Another possibility is to change the assignment to
coefA[i] = T();
This will assign a default constructed object of the type (0.0 for doubles).
What are the basic rules and idioms for operator overloading has detailed information on overloading operators.

Intializing a pointer from a class, from a different class type, C++

I am doing an assignment for my OOP C++ class. I am currently struggling with initializing a pointer. The directions for my assignment from this part state:
Define a class called FracList with private members fracPtr, a Fraction pointer and size to hold the size of the array of Fraction objects.
My current code, which brings errors, goes like this. Note Fraction is another class.
in FracList.h
private:
Fraction *fracPtr;
int size;
in FracList.cpp
void FracList::set_ptr(int* p)
{
fracPtr = p;
}
Fraction *FracList::get_ptr()
{
return fracPtr;
}
// Default Constructor
FracList::FracList(int s) : size(s)
{
if (size > 0)
fracPtr = new Fraction[size];
else
fracPtr = NULL;
}
How do I properly initialize the Fraction* fracPtr pointer variable?
So what you probably meant is this:
class Fraction{
public:
Fraction(){}
};
class FracList{
private:
Fraction *fracPtr;
int size;
public:
Fraction* get_ptr();
FracList(int s);
void set_ptr(Fraction* p);
};
void FracList::set_ptr(Fraction* p)
{
fracPtr = p;
cout<<"The address of p is:"<< p <<endl;
}
Fraction *FracList::get_ptr()
{
return fracPtr;
}
int main ()
{
FracList f1(3);
Fraction* p=new Fraction;
f1.set_ptr(p);
cout<<"the address of p is still:" << p << endl;
}
All that you have to do is to understand how to initialize a pointer. Fraction *fracPtr = p; This is the right way to do it and the parameter that you have to pass at this function is not an int, it should be a pointer to Fraction because you want to give to your data member an address that it will point to. The concept is similar to pointers in c :Pointer initialization concept in c

Operator overloading (--) sets variables to 0

When I call r--; My object resets the values to 0. Any ideas?
class MyClass : Superclass {
private:
int length;
int width;
public:
MyClass() {
length = 0;
width = 0;
}
MyClass (int x, int y):Superclass(x/2,y/2){
length = x;
width = y;
}
MyClass operator--(int) {
MyClass temp = *this;
temp.length --;
temp.width --;
return temp;
};
};
Creating and trying the class:
MyClass *r = new MyClass(2,3);
r--; // now length and width = 0 (should be 1,2)
Firstly, the operator doesn't decrement the object it's called on, but the copy it's going to return. It should leave that alone (to return the previous value) and decrement the object:
MyClass temp = *this;
this->length--; // this-> is optional
this->width--;
return temp;
Secondly, r is a pointer. r-- decrements the pointer, not the object it points to, leaving it pointing to an invalid memory location. Dereferencing it afterwards gives undefined behaviour.
I've no idea why you're using new here; you almost certainly just want a variable:
MyClass r(2,3);
r--; // should behave as expected.
If you really do want a pointer for some reason, you'll have to dereference it to get the object:
(*r)--;
and don't forget to delete the object once you've finished with it. And not before.

Combining declaration and initialization with overloaded `=`

I'm new to C++ (but not new to programming--I know Java pretty thoroughly), so this may have a simple answer I'm just overlooking.
Question in a nutshell: What (if anything) is the difference between writing:
classType a = b;
and writing
classType a;
a = b;
specifically when b is a reference variable in a function and when = is overloaded?
Details/background:
I'm working on a custom vect class, which will (eventually) hold n-tuples that behave like vectors in R^n (that is, math-style vectors, not STL-style vectors). As such, I've overloaded the = operator to copy the components from rhs to lhs.
However, I've found that, when my rhs is a reference variable in a function, the combined declaration/initialization makes the rhs and lhs reference the same object, while the separate initialization keeps them as different objects.
In my program below, this is evidenced as v2 = v1 * 10 results in both v2 and v1 being set equal to v1*10 when I use the single-line vect a = b, but behaves as expected when I write vect a; a=b in the definition of *.
Minimal Compilable Example:
I apologize for its length, but this is pared down as much as I could get it at first try. I'll keep looking for ways to reduce.
The problem occurs in the overloading of the * operator. I've commented there as to what change is required to exhibit the problem.
#include<iostream>
#include<string.h> //For toString method
#include<sstream> //For toString method
//===================================================
// Namespace for organization
namespace linalg {
class vect {
private:
//int length;
double* baseArray;
public:
//Constructor
vect() { baseArray = new double[3]; }
//TODO: Change so edits to arrayArg do not show up in the baseArray.
vect(double arrayArg[3]) { baseArray = arrayArg; }
//Returns a string for printing
std::string toString();
//Returns the element at given index
double getElementAt(int) const;
//Operator overloading:
vect& operator=(const vect &rhs);
friend vect operator*(double num, const vect &v);
};
//===================================================
// General Methods
// elementAt : return s the given element.
double vect::getElementAt(int i) const {
return baseArray[i];
}
// toString : behaves like Java convention:
//toString : gives string representation
std::string vect::toString() {
std::string retVal;
retVal.append("[");
for (int i = 0; i < 3; i++) {
//Convert the number to a string
std::ostringstream num;
num << baseArray[i];
//Append the number to the return value
retVal.append(num.str());
//Comma separated
if (i < 3-1) retVal.append(", ");
}
retVal.append("]");
return retVal;
}
//===================================================
// Operator overloads
//Overload '=' : copies the other vector into this vector
vect& vect::operator= (const vect &rhs) {
//Check for self-assignment:
if (this == &rhs) {
return *this;
}
//Copy the rhs into this vector
for (int i = 0; i < 3; i++) {
baseArray[i] = rhs.getElementAt(i);
}
return *this;
}
//Overload scalar multiplication
vect linalg::operator*(double num, const vect &v) {
//CHANGE THIS to a single-line assignment/initialization, and the problem occurs.
vect result;
result = v;
for(int i = 0; i < 3; i++) {
result.baseArray[i] *= num;
}
return result;
}
};
using namespace linalg;
using namespace std;
int main() {
double a[3] = {2, 4, 8};
double b[3] = {5, 1, 9};
vect v1(a);
vect v2(b);
v1 = 10*v2;
cout << v1.toString() << endl;
cout << v2.toString() << endl;
system("pause"); //Pause the windows terminal
return 0;
}
The difference is that vect a = b; performs copy initialization whereas vect a; a = b; performs copy assignment. Copy initialization calls the copy constructor, whereas copy assignment calls the overloaded operator=.
In your code, your copy assignment operator copies one vector's elements over into another, which is good. However, your copy constructor simply sets baseArray of the LHS to point to the same block of memory as that of the RHS, without copying any vector elements. When two pointers point to the same memory, of course modifying one also modifies the other.

Storing values in a struct in a linked list

I'm wondering how I would go about storing a value into a struct that is part of a linked list of structs. I have:
struct polynomial
{
polynomial(string newCoefficient, string newPower, polynomial *nextPtr);
string coefficient;
string power;
polynomial *next;
};
class linkedList
{
public:
void createList();
private:
polynomial *head;
};
For this assignment, we need to do some parsing when gathering input values. For example, we are to input two numbers separated by a space (ex. 7 9 or 10 8). Therefore, in void createList(), I want to read in a line using string, convert it to a char array to strip down the values, then store that value into polynomial.coefficient and polynomial.power, for each node in the linked list.
Or, I was searching some information up, and I was thinking maybe I can input two int values and then use stringstream to convert them into strings and them store into coefficient and power.
Either way, can you help introduce me to the concept of storing a value into a linked listed struct?
EDIT: I have added the overloaded constructor:
polynomial:: polynomial ( string newCoefficient, string newPower, polynomial *nextPtr )
{
coefficient = newCoefficient;
power = newPower;
next = nextPtr;
};
You are mixing C-style practice with C++ practice.
In C++, you generally separate the data from the container. Look at how std::list works.
Even if you don't want to get into templating, you can still do this:
struct polynomial {
string coefficient;
string power;
};
struct listnode {
polynomial data;
listnode *next;
};
If you really want to have the head concept, you can either keep a 'dummy head' where you store one listnode that has nothing in it.
Alternatively, if you really want the next pointer in polynomial and you want a way to copy over an existing element without nuking the pointer, just make a setter function:
void polynomial::set( const string& inCoeff, const string & inPower );
I tested the following code which may help you out:
struct Polynomial {
string coefficient;
string power;
Polynomial* next;
Polynomial(const string& coeff, const string& pow) : coefficient(coeff), power(pow), next(NULL) {}
};
// linked-list of Polynomials
struct LinkedList {
Polynomial* head;
LinkedList() : head(NULL) {}
// add to end of list
void add(const string& coeff, const string& pow) {
if(head == NULL)
head = new Polynomial(coeff, pow);
else {
Polynomial* n;
for(n = head; n->next != NULL; n = n->next);
n->next = new Polynomial(coeff, pow);
}
}
// check if results are correct
void print() {
for(Polynomial* n = head; n != NULL; n = n->next)
cout << n->coefficient << " " << n->power << endl;
}
};
// somewhere in main()
LinkedList ll;
...
// read input values
ll.add(coeff1, pow1);
ll.add(coeff2, pow2);
ll.add(coeff3, pow3);
// check results
ll.print();
Note your Polynomial struct members need not be strings. Instead you could just parse your input and store cofficient as float and power as int (All polynomial exponents are integers).