Overloading the input operator with an array of pointers - c++

for a class project I have a 2D array of pointers. I understand the constructors, destructors, etc. but I'm having issues understanding how to set the values in the array. We're using the overloaded input operator to input the values.
Here is the code I have for that operator so far:
istream& operator>>(istream& input, Matrix& matrix)
{
bool inputCheck = false;
int cols;
while(inputCheck == false)
{
cout << "Input Matrix: Enter # rows and # columns:" << endl;
input >> matrix.mRows >> cols;
matrix.mCols = cols/2;
//checking for invalid input
if(matrix.mRows <= 0 || cols <= 0)
{
cout << "Input was invalid. Try using integers." << endl;
inputCheck = false;
}
else
{
inputCheck = true;
}
input.clear();
input.ignore(80, '\n');
}
if(inputCheck = true)
{
cout << "Input the matrix:" << endl;
for(int i=0;i< matrix.mRows;i++)
{
Complex newComplex;
input >> newComplex;
matrix.complexArray[i] = newComplex; //this line
}
}
return input;
}
Obviously the assignment statement I have here is incorrect, but I'm not sure how it is supposed to work. If it's necessary that I include more code, let me know.
This is what the main constructor looks like:
Matrix::Matrix(int r, int c)
{
if(r>0 && c>0)
{
mRows = r;
mCols = c;
}
else
{
mRows = 0;
mCols = 0;
}
if(mRows < MAX_ROWS && mCols < MAX_COLUMNS)
{
complexArray= new compArrayPtr[mRows];
for(int i=0;i<mRows;i++)
{
complexArray[i] = new Complex[mCols];
}
}
}
and here is Matrix.h so you can see the attributes:
class Matrix
{
friend istream& operator>>(istream&, Matrix&);
friend ostream& operator<<(ostream&, const Matrix&);
private:
int mRows;
int mCols;
static const int MAX_ROWS = 10;
static const int MAX_COLUMNS = 15;
//type is a pointer to an int type
typedef Complex* compArrayPtr;
//an array of pointers to int type
compArrayPtr *complexArray;
public:
Matrix(int=0,int=0);
Matrix(Complex&);
~Matrix();
Matrix(Matrix&);
};
#endif
the error I'm getting is "cannot convert Complex to Matrix::compArrayPtr (aka Complex*) in assignment" If anyone can explain what I'm doing wrong, I'd be very grateful.

Your newComplex is an object of type Complex (a value) and you try to assign it to a Complex* pointer.
For this to work you should construct a complex dynamically:
Complex* newComplex = new Complex();
input >> *newComplex;
matrix.complexArray[i] = newComplex;
But be aware of all the consequences that come with dynamic allocation (memory management, ownership, shared state...).

Related

Why am i getting this error: could not convert '0' from 'long int' to 'Sparse'

I am creating a code for a sparse matrix, basically for adding two sparse matrices.
And now it's not working. showing some error with return NULL.
When checking for the condition that if the dimensions of the matrix are not the same, it will not execute the program as the condition will be false and it will return NULL but it's showing an error there.
#include<iostream>
using namespace std;
class Element{
public:
int i;
int j;
int x;
};
class Sparse{
private:
int m;
int n;
int num;
Element *ele;
public: // constructor
Sparse(int n ,int m , int num){
this->n = n;
this->m = m;
this->num = num;
ele = new Element[this->num];
}
~Sparse(){ // destructor
delete []ele;
}
//Global functions for insertion and extraction
Sparse operator+(Sparse &s);
friend istream & operator>>(istream &is , Sparse &s); // Insertion operator
friend ostream & operator<<(ostream &os , Sparse &s); // Extraction operator
};
Sparse Sparse::operator+(Sparse &s)
{
int i , j , k;
if(m!=s.m || n!=s.n)
return NULL;
Sparse *sum = new Sparse(m,n,num+s.num);
i=j=k=0;
while(i<num && j<s.num){
if(ele[i].i < s.ele[j].i){
sum->ele[k++] = ele[i++];
}else if(ele[i].i > s.ele[j].i){
sum->ele[k++] = s.ele[j++];
}else{
if(ele[i].j < s.ele[j].j){
sum->ele[k++] = ele[i++];
}else if(ele[i].j > s.ele[j].j){
sum->ele[k++] = s.ele[j++];
}else{
sum->ele[k]=ele[i];
sum->ele[k++].x = ele[i++].x +s.ele[j++].x;
}
}
}
for(;i<num;i++)sum->ele[k++] = ele[i];
for(;j<s.num;j++)sum->ele[k++] = s.ele[j];
sum->num = k;
return *sum;
}
// void read()
istream & operator>>(istream &is , Sparse &s)
{
cout<<"Enter non zero elements:";
for(int i=0;i<s.num;i++){
cin>>s.ele[i].i>>s.ele[i].j>>s.ele[i].x;
}
return is;
}
// void Display()
ostream & operator<<(ostream &os , Sparse &s)
{
int k = 0;
for(int i= 0; i<s.m;i++){
for(int j=0 ; j<s.n; j++){
if(s.ele[k].i ==i && s.ele[k].j ==j){
cout<<s.ele[k++].x<<" ";
}else{
cout<< "0 ";
}
}
cout<<endl;
}
return os;
}
int main(){
Sparse s1{5,5,5};
Sparse s2{5,5,5};
// s1.read();
// s1.Display();
cin>>s1;
cin>>s2;
Sparse sum=s1+s2;
cout<<"Enter First Matrix:"<<endl<<s1;
cout<<"Enter Second Matrix"<<endl<<s2;
cout<<"Sum Matrix"<<endl<<sum;
return 0;
}
If you go and see the definition of NULL, you will notice that
#define NULL 0
The NULL is replaced by a 0, which is a long int.
In some programming languages, like Java and C#, objects are passed around as pointers, and therefore you can just assign them to null. C++, however, somehow works similar to a struct -- it is passed by value.
Sparse Sparse::operator+(Sparse &s) means that the operator will return a Sparse type. As classes are passed by value, it will return the object's data, a series of bytes. That means you can't just return a NULL to indicate that the concatenation had failed.
An alternative would be to throw an exception. You can also rewrite the operator to a method that returns a Sparse*, a pointer to a Sparse.
Sparse* addSparse(Sparse s1, Sparse s2) {
if(s1.m != s2.m || s1.n != s2.n)
return NULL;
// add them together
}
That way, the caller can check if the concatenation is successful by checking the returned value.
Sparse* result = addSparse(s1, s2);
if(result != NULL) {
// Consume the result
}
// Handle it

I have a problem with reading & printing my class

I have a problem with printing my class. I want this class to read a binary number and then print it. I am a Beginner, so here can be a really dumb mistake.
This code has a wrong output, but a correct input.
I tried to fix this, but I couldn't. I hope you will find the mistake.
Please help. Thanks!
Here is the code:
#include <iostream>
using namespace std;
class Binary
{
int len;
bool* arr;
public:
Binary();
Binary(const Binary&);
friend istream& operator >> (istream&, Binary&);
friend ostream& operator << (ostream&, const Binary&);
};
Binary::Binary()
{
len = 0;
arr = new bool[0];
}
Binary::Binary(const Binary& b)
{
len = b.len;
arr = new bool[len];
for (int i = 0; i < len; i++) {
arr[i] = b.arr[i];
}
}
istream& operator>>(istream& in, Binary& b)
{
char line[101];
in.getline(line, 100);
b.len = strlen(line);
b.arr = new bool[b.len];
for (int i = 0; i < b.len; i++) {
b.arr[i] = (line[i] == '0' ? 0 : 1);
}
return in;
}
ostream& operator<<(ostream& out, const Binary& b)
{
for (int i = 0; i < b.len; i++) {
out << b.arr;
}
return out;
}
int main() {
Binary a;
cin >> a;
cout << a;
return 0;
}
The problem is with this line of code:
out << b.arr;
You are printing the array pointer, b.arr, instead of a value in the array.
This will work:
out << b.arr[i] ? '1' : '0';
You should also consider writing a destructor to free your previously allocated memory, and also free the previous array before overwriting it's pointer on this line:
b.arr = new bool[b.len];

Dynamic matrix in class

I have problem with dynamic allocation in c++.
This is my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Wektor {
int rozmiar;
float *TabWe;
friend std::istream& operator >> (std::istream &Strm, Wektor &Wek);
public:
Wektor(int rozmiar) : rozmiar(rozmiar) {
TabWe = new float[rozmiar];
}
Wektor() {
for (int i = 0; i < rozmiar; i++)
{
TabWe[i] = 0;
}
}
~Wektor()
{
for (int i = 0; i <rozmiar; i++)
{
delete[] TabWe;
}
}
};
istream& operator >>(istream &Strm, Wektor &Wek)
{
cout << "Size: ";
Strm >> Wek.rozmiar;
for (int i = 0; i < Wek.rozmiar; i++)
{
Strm >> Wek.TabWe[i];
}
return Strm;
}
int main()
{
Wektor wek;
cin >> wek;
}
After I enter first value to the matrix I get this error:
I think there is problem with default constructor, because you can see on the screenshot that this matrix has no value when program starts. What is wrong with it?

Operator overloading in C++ of a matrix template

I'm trying to implement a Matrix template. I've overloaded the <<, >> and + operators. << and >> are working properly but + is not working as expected. After using the + operator I am getting some random output in the last line. Can anyone tell me what is wrong?
#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
int row,col;
V **a;
mat(int r,int c)
{
row=r;
col=c;
a=new V*[r];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
}
mat(const mat &x) //Copy constructor
{
row=x.row;
col=x.col;
a=new V*[row];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
a[i][j]=x.a[i][j];
}
}
}
~mat()
{
//cout << "Deleting Matrix\n" << endl;
for(int i=0;i<row;i++)
{
delete []a[i];
}
}
friend ostream &operator<<(ostream &p,const mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p << z.a[i][j] <<" ";
}
cout << endl;
}
return p;
}
friend istream &operator>>(istream &p,mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p >> z.a[i][j];
}
}
return p;
}
mat<V> operator+(mat<V> z)
{
mat<V> b(row,col);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
b.a[i][j]=a[i][j]+z.a[i][j];
}
}
return b;
}
};
int main()
{
mat<int> p(2,2),q(2,2),z(2,2);
cin>>p>>q;
cout<<p<<q<<endl; //working properly
z=p+q;
cout<<z<<endl; // getting wrong output here
return 0;
}
In C++, I recommand to use operator +=, -=, *=, /= and others like them be internal to the class. The operators +, *, -, / should be external.
So you could do something like this:
class A {
A &operator +=(A const &b) {
... code
return *this;
}
};
A operator+(A a1, A const &a2) {
return a1 += a2;
}
thanks to vsoftco for the tip
To answer more precisely to your question, you just did not define the operator=
If you do mat z = p + q; it will works ;).
See my comments below for further details ;)
Inside of your operator+ you effectively have b = (*this) + z. You only however, check row and col from this. If z is smaller in either dimension you are going to be out of bounds.
You can check for this condition and figure out what to return if that happens (or throw an exception, the choice is yours):
mat<V> operator+(const mat<V>& z) const {
mat<V> b(row,col);
if (z.row != row || z.col != col) { return b; }
// ...
}
Or you can have the mat class be templated on the dimensions as well, which would make two different size matrices be different types
template <typename T, int Row, int Col>
class mat {
private:
T a[Row][Col];
// ...
};
The internals of your functions are working fine. But as others have mentioned above, there is something wrong with your function signatures, that is causing them to be called in a rather strange way.
I have added some debug output to your code to illustrate what is happening. You should add these changes, compile and run.
#include<iostream>
using namespace std;
template <class V>
class mat
{
public:
int row,col;
V **a;
mat(int r,int c)
{
row=r;
col=c;
a=new V*[r];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
for (int cc=0; cc<col;++cc)
{
a[i][cc] = -77;
}
}
}
mat(const mat &x) //Copy constructor
{
cout << "copy to this: " << this << endl;
cout << "x: " << &x << endl;
row=x.row;
col=x.col;
a=new V*[row];
for(int i=0;i<row;i++)
{
a[i]=new V[col];
}
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
a[i][j]=x.a[i][j];
}
}
}
~mat()
{
//cout << "Deleting Matrix\n" << endl;
for(int i=0;i<row;i++)
{
delete []a[i];
}
}
friend ostream &operator<<(ostream &p,const mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p << z.a[i][j] <<" ";
}
cout << endl;
}
return p;
}
friend istream &operator>>(istream &p,mat &z)
{
for(int i=0;i<z.row;i++)
{
for(int j=0;j<z.col;j++)
{
p >> z.a[i][j];
}
}
return p;
}
mat<V> operator+(mat<V> z)
{
cout << "plus to this: " << this << endl;
mat<V> b(row,col);
for(int i=0;i<row;i++)
{
for(int j=0;j<col;j++)
{
b.a[i][j]=a[i][j]+z.a[i][j];
}
}
return b;
}
};
int main()
{
mat<int> p(2,2),q(2,2),z(2,2);
cin>>p>>q;
cout<<p<<q<<endl; //working properly
cout << "Before" << endl;
cout << "p : " << &p << endl;
cout << "q : " << &q << endl;
cout << "z : " << &z << endl;
cout << "After" << endl;
z=p+q;
cout<<q<<endl;
cout<<z<<endl; // getting wrong output here
return 0;
}
When I run I see the following output.
Before
p : 0026F75C
q : 0026F748
z : 0026F734
After
copy to this: 0026F61C
x: 0026F748
plus to this: 0026F75C
copy to this: 0026F654
x: 0026F5E8
From this you can see that when the line
z=p+q;
is run, the copy constructor is called to copy q to an anonymous object, then the operator+ function is called on another anonymous object.
Finally, when exiting the operator+ function, the copy constructor is called again, copying the result of operator+ function to a third anonymous object. At no time is anything copied to z, nor is the operator+ function called on p or q.
This code also segfaults on exit. I think the problem lies with creating anonymous objects, which is using the default constructor created by the compiler, which does not set row, col or intialise a.

C++ Overloading operator >> (input) doesn't change original

I'm trying to build a custom dictionary class with custom string and definition classes. While trying to overload the >> (input) I get some kind of a problem. when the function ends the dictionary sent to it doesn't change. attaching the code:
This is the overloading:
istream& operator>>(istream& ip, Dictionary& var) {
Definition temp;
ip >> temp;
var += temp;
return ip;
}
and some other functions used in it:
Dictionary& Dictionary::operator+=(Definition& input) {
if (!checkCopy(input))
{
Definition** temp;
temp = new Definition*[numWords + 1];
for (int i = 0; i < numWords; i++)
{
temp[i] = book[i];
}
numWords++;
temp[numWords - 1] = &input;
delete[] book;
book = temp;
}
return *this;
}
Dictionary::Dictionary(Dictionary& input) {
*this = input;
}
Dictionary& Dictionary::operator=(Dictionary& input) {
if (numWords != 0)
delete[] book;
book = new Definition*[input.numWords];
for (int i = 0; i < input.numWords; i++)
{
*this += *input.book[i];
}
return *this;
}
And the class itself:
class Dictionary
{
private:
int numWords = 0;
Definition** book;
public:
Dictionary();
~Dictionary();
Dictionary(Dictionary&);
bool operator==(Dictionary&) const;
Dictionary& operator=(Definition&);
Dictionary& operator=(Dictionary&);
friend ostream& operator<<(ostream&, const Dictionary&);
friend istream& operator>>(istream&, Dictionary&);
Dictionary& operator-=(int);
Dictionary& operator+=(Definition&);
bool checkCopy(Definition&);
Definition& operator[](int); //left side brackets for input
Definition operator[](int) const; //right side brackets for output
};
EDIT: here is also the overloading operator for definition input:
istream& operator>>(istream& ip, Definition& var)
{
cout << "Please enter a word: " << endl;
ip >> var.word;
cout << "Please enter the number of definitions for this word: " << endl;
int idx;
cin >> idx;
while (idx<0)
{
cout << "Error: number of definitions not possible. Please Try again: " << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
cin >> idx;
}
cin.clear();
cin.ignore(INT_MAX, '\n');
String* temp = new String[idx];
for (int i = 0; i < idx; i++) {
cout << "Please enter the " << i + 1 << "th definition: " << endl;
cin >> temp[i];
var += temp[i];
}
var.sortDefinition();
return ip;
}
Help is indeed needed.
You should really stick to std::vector and other collection types rather than juggling around with pointers and new/delete as you do here.
In your operator+= function you're copying the address of a temporary variable into your array:
temp[numWords - 1] = &input;
Once the calling function operator>> ends, this pointer is less than worthless, because the original object (Definition temp;) does not exist any longer. Therefore the behaviour of that code is undefined!
You might get around this by defining a copy c'tor for Definition and then changing above line to:
*temp[numWords - 1] = input;
Also in your assignment operator you're making use of the operator+= function. However, your numWords member is not set appropriately at this time, so operator+= will likely do the wrong thing. So add a line to the assignment operator like this:
if (numWords != 0)
{
delete[] book;
numWords = 0; // add this line
}
There were 2 problems:
what Alexander said about the temporary variable. changed it to:
Dictionary& Dictionary::operator+=(Definition& input) {
if (!checkCopy(input))
{
Definition** temp;
temp = new Definition*[numWords + 1];
temp[0] = new Definition[numWords];
for (int i = 0; i < numWords; i++)
{
temp[i] = book[i];
}
temp[0][numWords] = input;
delete[] book;
book = temp;
numWords++;
}
return *this;
}
The second was that in the Definition class when I tried to access the number of definitions in an object that wasn't created due to the double pointer:
Definition** temp;
temp = new Definition*[numWords + 1];
So I changed it so it won't access it but first build it.
Thanks for the help Alexander!