Overloading operator >> in C++ - c++

#include<iostream>
using namespace std;
class term
{
public:
int exp;
int coeff;
};
class poly
{
public:
term* term_ptr;
int no_term;
poly(int d);
friend istream& operator>>(istream& in, poly& p);
friend ostream& operator<<(ostream& out, const poly& p);
friend poly operator+(const poly& p1, const poly& p2);
};
poly::poly(int d=0)
{
no_term = d;
term_ptr = new term[no_term];
}
istream& operator>>(istream& in, poly& p)
{
in>>p.no_term;
for(int i= 0; i<p.no_term; i++)
{
in>>(p.term_ptr+i)->coeff;
in>>(p.term_ptr+i)->exp;
}
return in;
}
i overloaded the input operator to input the object. The problem I am facing is when i input two objects consequtively the data member of the first object input changes.
int main(void)
{
poly p1, p2;
cin>>p1;
cin>>p2;
cout<<p1;
cout<<p2;
return 0;
}
if the input is
3
1 1
1 2
1 3
3
1 1
1 2
1 3
the output i get is
1 1
1 2
1 1
1 1
1 2
1 3
the output operator function is
ostream& operator<<(ostream& out, const poly& p)
{
out<<"coeff"<<" "<<"power"<<endl;
for(int i = 0; i< p.no_term; i++)
out<<(p.term_ptr+i)->coeff<<" "<<(p.term_ptr+i)->exp<<endl;
return out;
}

You initially allocate an array with zero elements. When reading the objects you read the number of terms but you don't reallocate the array of terms. I would personally recommend to use a suitable container type, e.g., std::vector<term*> or, actually, std::vector<std::shared_ptr<term>>. If you stick with arrays, you'd need something like this:
std::istream& operator>>(std::istream& in, poly& p)
{
if (in>>p.no_terms ) {
std::unique_ptr<term[]> terms(new term[p.no_terms]);
for(int i= 0; i<p.no_term; i++)
{
in >> terms[i].coeff;
in >> terms[i].exp;
}
if (in) {
delete[] p.term_ptr;
p.term_ptr = terms.release();
}
}
return in;
}

Change poly p1, p2; to poly p1(3), p2(3);.
p.no_term has a value of 3, however, look at your poly constructor:
poly::poly(int d=0)
{
no_term = d;
term_ptr = new term[no_term];
}
You are creating an array of 0 length. Also, no need to use pointer in your code. Here is an example using std::vector<term>:
#include<iostream>
#include <vector>
using namespace std;
class term
{
public:
int exp;
int coeff;
};
class poly
{
public:
std::vector<term> term_vec;
int no_term;
poly(int d);
friend istream& operator>>(istream& in, poly& p);
friend ostream& operator<<(ostream& out, const poly& p);
friend poly operator+(const poly& p1, const poly& p2);
};
poly::poly(int d=0) : term_vec(d), no_term(d)
{
}
istream& operator>>(istream& in, poly& p)
{
in>>p.no_term;
p.term_vec.resize(p.no_term);
for(int i= 0; i<p.no_term; i++)
{
in>> p.term_vec[i].coeff;
in>> p.term_vec[i].exp;
}
return in;
}
ostream& operator<<(ostream& out, const poly& p)
{
out<<"coeff"<<" "<<"power"<<endl;
for(int i = 0; i< p.no_term; i++)
out<<p.term_vec[i].coeff<<" "<<p.term_vec[i].exp<<endl;
return out;
}
int main(void)
{
poly p1, p2;
cin>>p1;
cin>>p2;
cout<<p1;
cout<<p2;
return 0;
}

Your default constructor argument d has value 0. Then you call new term[0]. Pointers that initialize as arrays with 0 length is pointed in same location in your example. After your fill non-valid memory and see same results.

Related

Data loss every time I push an object into a vector

I have a school project in which I am supposed to build a template class Vanzare meaning sale. I have 2 STL vectors, one for the cars that are in stock, and one for the cars that are sold, and 2 variables that count how many cars are in stock and how many cars are sold.
The class is supposed to have the -= operator overloaded, and it's supposed to sell a car, meaning deleting it from the stock vector (named stoc) and adding it to the sold vector (named vandut).
I also overloaded the += operator to add a car to stock.
The types of cars I have are all derived from the base class Masina, and some of them have extra fields.
The problem is that whenever I use += or -= ( or push_back() in general) for anything that has extra fields (compared to the base class), it breaks the previous elements from the vector. So I can't store any derived objects without loss of information.
I was also told that making a specialization of the whole class might help, but it didn't.
The template class starts around line 300 (I didn't know how to highlight it sorry). I am sorry if what I wrote wasn't clear, I am kinda new to all of this object oriented stuff. Thank you in advance!
Edit: I tried my best to slim the program down as much as I can, but it still has 250 lines of code. I also renamed (hopefully everything) to English. The field sh still gets lost when I add an object to the vector.
#include <iostream>
#include <string.h>
#include <vector>
#include <ctime>
using namespace std;
class Car
{
int capacity;
float length;
int price;
int year;
public:
int getYear();
void setPrice(int);
int getPrice();
Car();
~Car();
Car(int , float , int , int);
Car(const Car&);
friend istream& operator>>(istream& , Car&);
friend ostream& operator<<(ostream& , Car&);
friend class VAN;
};
int Car::getYear()
{
return year;
}
int Car::getPrice()
{
return price;
}
void Car::setPrice(int p)
{
price = p;
}
ostream& operator<<(ostream& out , Car& m)
{
out<<"capacity: "<<m.capacity<<"\nlength: "<<m.length<<"\nprice: "<<m.price<<"\nYear: "<<m.year;
return out;
}
istream& operator>>(istream& in , Car& m)
{
cout<<"capacity: ";
in>>m.capacity;
cout<<"length: ";
in>>m.length;
cout<<"price: ";
in>>m.price;
cout<<"Year: ";
in>>m.year;
return in;
}
Car::Car()
{
capacity = 0;
length = 0;
year = 0;
price = 0;
}
Car::Car(int lit , float lun , int an , int pre)
{
capacity = lit;
length = lun;
year = an;
price = pre;
}
Car::Car(const Car& m)
{
capacity = m.capacity;
length = m.length;
year = m.year;
price = m.price;
}
Car::~Car()
{
capacity = 0;
year = 0;
length = 0;
price = 0;
}
class VAN:public Car
{
int sh;
public:
void setSH(int);
int isSH();
VAN();
~VAN();
VAN(int , float , int , int , int);
VAN(const VAN&);
friend istream& operator>>(istream& , VAN&);
friend ostream& operator<<(ostream& , VAN&);
};
void VAN::setSH(int s)
{
if(s)
sh = 1;
else
sh = 0;
}
int VAN::isSH()
{
return sh;
}
ostream& operator<<(ostream& out , VAN& m)
{
out<<(Car&)m;
out<<endl<<"Second hand: "<<m.sh;
return out;
}
istream& operator>>(istream& in , VAN& m)
{
in>>(Car&)m;
cout<<"Second Hand: ";
int x;
in>>x;
if(x)
m.sh = 1;
return in;
}
VAN::VAN():Car()
{
;
}
VAN::~VAN()
{
;
}
VAN::VAN(int a , float b , int c, int d , int s):Car(a , b, c , d)
{
if(s)
sh = 1;
}
VAN::VAN(const VAN& m):Car(m)
{
;
}
template <class T>
class Sale
{
vector<T> stock;
vector<T> sold;
int nrSold;
int nrStock;
public:
Sale();
Sale<T>& operator += (T&);
template <class U>
friend ostream& operator<<(ostream& , Sale<U>& );
Sale<T>& operator -= (int);
};
template <class T> Sale<T>& Sale<T>::operator -= (int i)
{
nrStock--;
nrSold++;
sold.push_back(stock[i]);
stock.erase(stock.begin()+i);
time_t now = time(0);
tm *ltm = localtime(&now);
if(ltm->tm_mon == 5 || ltm->tm_mon == 6 || ltm->tm_mon == 7)
{
(sold[nrSold-1]).setPret((sold[nrSold-1].getPret()/10)*9);
}
return *this;
}
template <class T> Sale<T>::Sale()
{
nrSold = 0;
nrStock = 0;
}
template <class T> ostream& operator<<(ostream& out, Sale<T>& v)
{
out<<"\nWhat we have in stock:\n\n";
for(int i = 0; i < v.nrStock ; i++)
{
out<<v.stock[i]<<endl;
}
cout<<"\nWhat we sold:\n\n";
for(int i = 0; i < v.nrSold ; i++)
{
out<<v.sold[i]<<endl;
}
return out;
}
template <class T> Sale<T>& Sale<T>::operator += (T& t)
{
nrStock ++;
stock.push_back(t);
return *this;
}
int main()
{
VAN x;
cin>>x;
cout<<x;
Sale<VAN> v;
v += x;
v += x;
cout<<v;
}
There are logic errors in ALL of your VAN constructors:
in the default constructor, the sh member is not being initialized at all, so it's value is indeterminate.
In the conversion constructor, the sh member is not being initialized if the s parameter is 0, so it's value is indeterminate in that case. Your operator>> has a similar logic error that it is not updating the m.sh member if the input is 0.
in the copy constructor, the sh member is not being copied from m at all, so it's value is indeterminate.
When you push a VAN object into your vector, a copy of the object is made. And if the vector needs to reallocate its array to grow its capacity, new copies of existing elements are made. Since your copy constructor is broken, that is why you are losing your sh values.
Your VAN constructors need to look more like this instead 1:
VAN::VAN() : Car(), sh(0)
{
}
VAN::VAN(int a , float b , int c, int d , int s) : Car(a , b, c , d)
{
sh = (s != 0);
}
VAN::VAN(const VAN& m) : Car(m), sh(m.sh)
{
}
1: in the case of the copy constructor, you can actually omit it completely, and let the compiler auto-generate a suitable copy constructor for you.
And your operator>> needs to look more like this instead:
istream& operator>>(istream& in , VAN& m)
{
in >> (Car&)m;
cout << "Second Hand: ";
int x;
in >> x;
m.sh = (x != 0);
return in;
}
On a couple of side notes:
your sh member is declared as an int, but it clearly should be a bool instead.
VAN does not need to, and should not, be declared as a friend of Car. If VAN needs direct access to Car's private members, they should be declared as protected instead.

Memory leak,copy constructor,assign operator

Everthing is in the code
Here is code. Constructor's.
Polynomial::Polynomial()
{
base=0;
Coefficients=new int [base+1];
Coefficients[0]=0;
}
Basically creates Poly equals to 0;
Polynomial::Polynomial(const unsigned int length,const int* table)
{
base=length;
bool a=false;
for(int i=length;i>=0;i--)
{
if(table[i]==1&&a==false)
{
a=true;
Coefficients=new int[base+1];
};
if(table[i]==0&&a==false)
{
base--;
};
if(a==true)
Coefficients[i]=table[i];
}
}
Here we create Poly with given length(it can be higher than Poly base)
I think so far everything is ok.
Now copy constructor:
Polynomial::Polynomial(const Polynomial& P)
{
base = P.base;
Coefficients=new int[base+1];
for(unsigned int i=0; i<base+1;i++)
{
Coefficients[i]=P.Coefficients[i];
}
}
And assign operator:
Polynomial& Polynomial::operator =(const Polynomial &P)
{
base=P.base;
for(unsigned int i=0;i<P.base+1;i++)
Coefficients[i]= P.Coefficients[i];
return *this;
}
I think there is smth wrong with this because when i overloaded + operator
And created Polynomial a,u,v;
When i typed a=v+u;
Sometimes i had garbage values and " Process returned -1073741819 (0xC0000005)"
I've read some about switch/copy but is there simple solution in my code that I am missing on?
Polynomial operator +(const Polynomial& a,const Polynomial& b)
{
Polynomial c;
if(a.base>=b.base)
c.base=a.base;
else
c.base=b.base;
c.Coefficients=new int[c.base+1];
for(unsigned int i=0;i<c.base+1;i++)
{
c.Coefficients[i]=0;
};
for(unsigned int i=0;i<b.base+1;i++)
{
c.Coefficients[i]=b.Coefficients[i];
};
for(unsigned int i=0;i<a.base+1;i++)
{
c.Coefficients[i]+=a.Coefficients[i];
}
return c;
}
Here is destructor
Polynomial::~Polynomial()
{
delete []Coefficients;
}
+= operator
Polynomial& Polynomial::operator +=(const Polynomial& a)
{
if(a.base>base)
{
base=a.base;
Coefficients = (int*)realloc(Coefficients, (base+1)*sizeof(int));
for(unsigned int i=0;i<base+1;i++)
{
if(Coefficients[i]!=0&&Coefficients[i]!=1)
{
Coefficients[i]=0;
}
Coefficients[i]+=a.Coefficients[i];
}
}
if(a.base<=base)
{
for(unsigned int i=0;i<a.base+1;i++)
{
Coefficients[i]+=a.Coefficients[i];
}
}
return *this;
}

Polynomial code

I'm working on an assignment for my C++ class and have run into a little problem when running the program. I get an error stating Unhandled exception at 0x000944C8 in Pog11.exe: 0xC0000005: Access violation writing location 0x00000000. while debugging. The goal is to read in the int degree of a polynomial, as well as the double coefficients.
here is the .h file that I was supplied:
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include<iostream>
using std::ostream;
using std::istream;
using std::cerr;
using std::endl;
class Polynomial
{
friend ostream& operator<<( ostream& left , const Polynomial& right);
friend istream& operator>>( istream& left , Polynomial& right );
public:
Polynomial();
Polynomial( int degree, const double* coefficients );
Polynomial( const Polynomial& );
~Polynomial();
const Polynomial& operator=( const Polynomial& deg);
bool operator==( const Polynomial& deg ) const;
void setDegree(int d);
int getDegree() const;
private:
int degree;
double* coefficients;
};
#endif
And here is the segment of code that is causing the error:
istream& operator>>(istream& left, Polynomial& right)
{
int tmp;
left >> tmp;
right.setDegree(tmp);
int i = 0;
while (i<=right.getDegree())
{
double co;
left >> co;
right.coefficients[i] = co;
i++;
}
return left;
}
Specifically the right.coefficients[i]=co; line is what causes the program to crash.
Here are the constructors for the class:
#include "Polynomial.h"
Polynomial::Polynomial() :degree(0), coefficients(0)
{
degree = 0;
coefficients = new double[degree];
}
Polynomial::Polynomial(int deg, const double* coefficients)
{
if (deg < 0)
{
degree = 0;
}
else
{
degree = deg;
}
coefficients = new double [degree];
}
Polynomial::Polynomial(const Polynomial& deg)
{
if (deg.getDegree() <= 0)
{
setDegree(0);
}
else
{
setDegree(deg.getDegree());
for (int i = 0; i < degree; i++)
{
coefficients[i] = deg.coefficients[i];
}
}
}
There's code missing - e.g. the implementation of the constructor of the Polynomial object.
I'm pretty sure that your error is that you have not allocated (enough) memory for the coefficients data member. There must be a
coefficients = new double[number_of_coeffs]
somewhere in your code.
EDIT
There's a number of points where you need to do this: where the degree of the polynomial is (re)set. Because then you know the degree of the polynomial:
Here you must copy the elements passed:
Polynomial( int degree, const double* coefficients ):
coefficients( new double[degree] ), degree( degree )
{
::memcpy(this->coefficients, coefficients, degree * sizeof(double));
}
and in this one, the degree of the polynomial changes - so your coefficients array must be modified accordingly.
Polynomial::setDegree( int degree ) {
// first delete the old coefficients
delete [] coeffs;
// and make a new array
this->degree = degree;
this->coefficients = new double[ this->degree ];
// initialize the coefficients
..
}
Similar actions have to be done in the copy constructor and the assignment operator.
Finally: you might be better off using std::vector<double> which basically does all the memory management for you. See http://en.cppreference.com/w/cpp/container/vector

error: overloaded 'operator<<' must be a binary operator (has 3 parameters)

I know there are plenty of questions like these, but I couldn't find a solution that worked for me.
I am trying to make simple fraction calculator than can add or subtract any number of functions and write the answer as a reduced fraction.
Example: input=
3/2 + 4/
8
, output =
2
I am trying overload operators in order to accomplish this.
So in the program I am trying to develop, the input consists of an expression made of fractions separated by the operators + or -.
The number of fractions in the expression is arbitrary.
Each of the following 6 lines is an example of a valid input expression:
1/2 + 3/4
1/2 -5/7+3/5
355/113
3 /9-21/ -7
4/7-5/-8
-2/-3+7/5
***The problem that I am having is that in when I run my program it has an overload operating error: *error: overloaded 'operator<<' must be a binary operator (has 3 parameters)****
/Users/Spicycurryman/Desktop/ECS40/hw1/fraction.cpp:61:22: error: overloaded 'operator<<' must be a binary operator (has 3 parameters)
ostream& Fraction::operator<<(ostream &os, Fraction& n)
^
/Users/Spicycurryman/Desktop/ECS40/hw1/fraction.cpp:80:22: error: overloaded 'operator>>' must be a binary operator (has 3 parameters)
istream& Fraction::operator>>(istream &os, Fraction& n)
I don't understand why that is an error.
My following code is below:
CPP FILE
#include "Fraction.h"
Fraction::Fraction(int a, int b)
{
}
int Fraction::find_gcd (int n1, int n2)
{
int gcd, remainder;
remainder = n1 % n2;
while ( remainder != 0 )
{
n1 = n2;
n2 = remainder;
remainder = n1 % n2;
}
gcd = n2;
return (gcd);
}
void Fraction::reduce_fraction(int nump, int denomp)
{
this->nump = nump;
this->denomp = denomp;
int gcd;
gcd = find_gcd(nump, denomp);
nump = nump / gcd;
denomp = denomp / gcd;
if ((denomp<0 && nump < 0 ))
{
denomp*=-1;
nump*=-1;
}
else if (denomp < 0 && nump >0){
denomp*=-1;
}
if ( denomp ==0) {
throw invalid_argument( "Error: zero denominator" );
}
}
Fraction& Fraction::operator+(const Fraction& n) {
denom = denomp * n.denom;
numera = (nump * n.numera) + (n.denom * n.nump);
return (*this);
}
Fraction& Fraction::operator-(const Fraction& n) {
denom = denomp * n.denom;
numera = (nump * n.numera) - (n.denom* n.nump);
return (*this);
}
ostream& Fraction::operator<<(ostream &os, Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os;
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
istream& Fraction::operator>>(istream &os, Fraction& n)
{
char slash = 0;
return os >> n.numera >> slash >> n.denom;
}
Header File
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
#include <stdexcept>
using namespace std;
class Fraction{
public:
Fraction(int a, int b);
int fraction(int a,int b);
int find_gcd(int n1, int n2);
void reduce_fraction(int nump, int denomp);
Fraction& operator+(const Fraction& n);
Fraction& operator-(const Fraction& n);
friend ostream& operator<<(ostream &os, const Fraction& n);
friend istream& operator>>(istream &is, const Fraction& n);
private:
int denom;
int numera;
int denomp;
int nump;
};
#endif
MAIN CPP FILE
#include "Fraction.h"
#include <iostream>
using namespace std;
int main()
{
Fraction x(2,3);
Fraction y(6,-2);
cout << x << endl;
cout << y << endl;
cin >> y;
cout << y << endl;
Fraction z = x + y;
cout << x << " + " << y << " = " << z << endl;
}
I know that the operators are member functions and a member function takes an implicit first parameter, meaning my operators now takes three parameters it may be fixed being a non-member function; however, that would not work in this program. How exactly in my case would I fix it so the program would work?
Thank you very much!
The problem is that you declared operator>> and operator<< as non-member functions, but defined as a member function.
This should fix that problem (but open another set of problems). So instead of
ostream& Fraction::operator<<(ostream &os, Fraction& n)
{
...
istream& Fraction::operator>>(istream &os, Fraction& n)
{
...
implement as :
ostream& operator<<(ostream &os, Fraction& n)
{
...
istream& operator>>(istream &os, Fraction& n)
{
...
Also, take a note that you declared functions as :
friend ostream& operator<<(ostream &os, const Fraction& n);
friend istream& operator>>(istream &is, const Fraction& n);
but defined as (therefore you changed the signature) :
ostream& Fraction::operator<<(ostream &os, Fraction& n)
istream& Fraction::operator>>(istream &os, Fraction& n)
Proper way is to declare and define as :
ostream& Fraction::operator<<(ostream &os, const Fraction& n)
istream& Fraction::operator>>(istream &os, Fraction& n)
I am adding just changes. The rest is the same as in the question:
class Fraction{
friend ostream& operator<<(ostream &os, const Fraction& n);
friend istream& operator>>(istream &is, Fraction& n);
// the rest is the same
};
ostream& operator<<(ostream &os, const Fraction& n)
{
if (n.numera == 0)
{
cout << 0 << endl;
return os;
}
else if (n.numera == n.denom)
{
cout << 1 << endl;
return os;
}
else
{
cout << n.numera << '/' << n.denom << endl;
return os;
}
}
istream& operator>>(istream &os, Fraction& n)
{
char slash = 0;
return os >> n.numera >> slash >> n.denom;
}

Overloading Operators in C++ is giving me an error

When I try to use this line in main.cpp:
m3.array = m1.array+m2.array;
where m3, m1, and m2 are all objects of a class type Matrix, with an int[3][3] array -
I keep getting an error that deals with an incompatible assignment of type int[3][3] and int[3][3] to opperand '+'. I don't know the exact error, because I'm not at a computer to compile the program.
Here's the matrix.cpp I have:
#include <iostream>
#include <string>
#include "matrix.h"
using namespace std;
Matrix::Matrix()
{
m1.array = 0;
}
istream& opeator >>(istream& inp, Matrix& m1)
{
int i, j;
for (i = 0; i < 3;i++)
{
for (j=0; j < 3;j++)
{
inp >> m1.array[i][j];
}
}
return inp;
}
ostream& operator <<(istream& outp, Matrix& m1)
{
int i, j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
out<<m1.array[i][j]<<" "<<endl;
}
}
return outp;
}
Matrix operator + (const Matrix& m1, const Matrix& m2)
{
Matrix answer;
int i,j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
answer.array[i][j] = m1.array[i][j] + m2.array[i][j];
}
}
return answer;
}
Matrix operator - (const Matrix& m1, const Matrix& m2)
{
Matrix answer;
int i, j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
answer.array[i][j] = m1.array[i][j] - m2.array[i][j];
}
}
return answer;
}
Matrix operator * (const Matrix& m1, const matrix& m2)
{
Matrix answer;
int i, j, k;
for (i = 0;i<3;i++)
{
for (j = 0; j<3;j++)
{
for (k = 0; k<3;k++)
{
answer.array[i][j] = m1.array[i][k] + m2.array[k][j];
}
}
}
return answer;
}
and the matrix.h:
#ifndef MATRIX_H
#define MATRIX_H
using namespace std;
class Matrix
{
public:
Matrix();
friend istream& operator >>(istream&, Matrix&);
friend ostream& operator <<(ostream&, const Matrix&);
friend Matrix& operator +(const Matrix&, const Matrix&);
friend Matrix& operator -(const Matrix&, const Matrix&);
friend Matrix& operator *(const Matrix&, const Matrix&);
int array[3][3];
};
#endif
Matrix operator + (const Matrix& m1, const Matrix& m2)
This tells the computer how to add two Matrix objects, good job.
m3.array = m1.array+m2.array;
m1 and m2 are Matrix objects, but m1.array is not. That is a int[3][3] object. Luckily, the fix is very very simple:
m3 = m1 + m2;
The member array is of type int[3][3]. You are trying to add those two multi-dimensional arrays which has no meaning in C++.
I assume what you really want is:
m3 = m1 + m2;
which would call your overloaded operator.
Something else that is also suspicious is that your friend declarations and your actual definitions don't match up. The return types are different.