I am trying to learn operator overloading by working on overloading >> for a matrix class to enable the key-board based input for a matrix by calling sth such as
Matrix M1;
cin >> M1;
The operator overloading part is given in the following
istream &operator>>(istream &in, Matrix &m)
{
for (int i = 0; i < m.dx; ++i) {
for (int j = 0; j < m.dy; ++j)
in >> m.p[i][j];
}
return in;
}
It turns work that my implementation was not correct at all. Can you let me know why this implementation is wrong?
I implemented the above part by imitating an existing implementation of overloading >>, which has been proven to work fine in the matrix output part, like cout<< A; where A is a matrix
ostream &operator<<(ostream &out, const Matrix &m)
{
for (int i = 0; i < m.dx; ++i) {
for (int j = 0; j < m.dy; ++j)
out << m.p[i][j] << " ";
out << endl;
}
return out;
}
I believe that the problem with your operator >> is that you're using whatever dimensions already happen to be in the Matrix rather than trying to recover the dimensions from the input that you find.
I think that your best bet would be to have the operator << implementation preface the matrix with dimension information (such as the number of rows and columns) and then have the operator >> function read in that information. For example:
ostream &operator<<(ostream &out, const Matrix &m)
{
out << m.dx << ' ' << out.dy << '\n';
for (int i = 0; i < m.dx; ++i) {
for (int j = 0; j < m.dy; ++j)
out << m.p[i][j] << " ";
out << endl;
}
return out;
}
With this in hand, you can write your stream extraction operator as
istream &operator>>(istream &in, Matrix &m)
{
in >> m.dx >> m.dy;
/* Some sort of logic to ensure that you've allocated an array large enough to
* hold all the elements ...
*/
for (int i = 0; i < m.dx; ++i) {
for (int j = 0; j < m.dy; ++j)
in >> m.p[i][j];
}
return in;
}
This may not be the most aesthetically pleasing input and output operators, but they should get the job done.
If you want to make these operators a bit classier, consider outputting the elements of the matrix using some special character to delimit rows and columns. For example, you might try outputting the matrix
0 1 2
3 4 5
6 7 8
as
[[0 1 2][3 4 5][6 7 8]]
With this setup, the size information about the matrix is implicit in how the bracket grouping works. Then again, this may make it a bit trickier to read the input, since you wouldn't know in advance how large the matrix is. But go with what's easiest for yourself overall.
As an FYI, you probably don't want to use endl to delimit lines when writing a stream insertion operator. In addition to writing a newline, endl flushes the buffer. If your stream is hooked up to a network connection, you may not want to keep flushing the buffer whenever you have a new line of the matrix, since that could result in a lot of data getting sent in bursts (slow) rather than grouping it all together at once (fast).
Hope this helps!
I don't think your code is wrong particularly.
If pressed I would suggest checking the stream condition in the loop.
For your information, the following code worked when I tested:
struct Matrix {
static int const dx = 2, dy = 2;
int p[ dx ][ dy ];
};
istream &operator>>(istream &in, Matrix &m)
{
for (int i = 0; i < m.dx; ++i) {
for (int j = 0; j < m.dy; ++j)
if ( ! (in >> m.p[i][j]) ) return in;
}
return in;
}
int main() {
Matrix M1;
cin >> M1;
cout << M1;
}
Hope this helps
#include<iostream>
using namespace std;
class Array /*overload of subscript operator of 1D array*/
{
private: int *p;
public:
int length;
Array(int size = 0): length(size)
{
p=new int(length);
}
int& operator [](const int k)
{
return p[k];
}
};
class Matrix
{
private: Array *p;
public:
int r,c;
Matrix(int i=0, int j=0):r(i), c(j)
{
p= new Array[r];
}
Array& operator [](const int& i)
{
return p[i];
}
friend istream& operator >> (istream& in, Matrix& m);
/*friend ostream& operator << (ostream& out, Matrix& m);*/
};
istream& operator >> (istream& in, Matrix& m)
{
for(int i=0 ; i < m.r ; i++)
{
for(int j=0 ; j < m.c ; j++)
in >> m[i][j];
}
}
/*ostream& operator << (ostream& out, Matrix& m)
{
for(int i=0 ; i < m.r ; i++)
{
for(int j=0 ; j < m.c ; j++)
out << m[i][j] << " ";
out << endl;
}
}*/
/*Driver program*/
int main()
{
Matrix M1(3,3); /*for checking purpose*/
cin >> M1;
/*cout << "\n" << M1;*/
}
Related
I can enter the inputs but I'm not able to see the output when I run my code (CTRL+F5) in C++ in visual studio 2017. This code is written to overload the operator *, ">>" & "<<" through the friend functions. one constructor initializes the vector elements to zero while the other constructor is used to initialize the elements of vector through the array.
My code is as below:
//vector.h
#pragma once
const int SIZE = 3;
#include<iostream>
using namespace std;
class vector
{
int v[SIZE];
public:
vector();
vector(int *x);
friend vector operator *(vector a, int b);
friend vector operator *(int b,vector a);
friend istream & operator >>(istream &input, vector &x);
friend ostream & operator <<(ostream &output, vector &y);
};
//vector.cpp
#include "vector.h"
#include<iostream>
using namespace std;
vector::vector()
{
for (int i = 0; i < SIZE; i++)
v[i] = 0;
}
vector::vector(int *x)
{
for (int i = 0; i < SIZE; i++)
v[i] = x[i];
}
vector operator *(vector a, int b) {
vector temp;
for (int i = 0; i < SIZE; i++)
temp.v[i] = a.v[i]*b;
return temp;
}
vector operator *(int a, vector b) {
vector temp;
for (int i = 0; i < SIZE; i++)
temp.v[i] = a * b.v[i];
return temp;
}
istream & operator >>(istream &input, vector &x) {
for (int i = 0; i < SIZE; i++)
input >> x.v[i];
return (input);
}
ostream & operator <<(ostream &output, vector &y) {
output << "(" << y.v[0];
for (int i = 1; i < SIZE; i++)
output <<","<< y.v[i];
output << ")";
return (output);
}
//main.cpp
#include "vector.h"
#include<iostream>
using namespace std;
int x[SIZE] = { 2,4,6 };
int main() {
vector m;
vector v2 = x;
cout << "Enter the elements of vector m:" << "\n";
cin >> m;
cout << "\n";
vector m1, m2;
m1 = m * 2;
m2 = 2 * v2;
cout << "m= "<<m<<"\n";
cout << "\n";
cout << "m1= " << m1 << "\n";
cout << "m2= " << m2 << "\n";
cin.get();
return 0;
}
Probably your linker settings are incorrect. Go to menu item Project/Properties. Then in the dialog find Configuration Properties/Linker/System/Subsystem and make sure it says Console (/SUBSYSTEM:CONSOLE).
Evgeny is correct cin.get() is not guaranteed to halt your program because there are still characters waiting to be read from cin that are left over from previous reads.
Your code assumes you must enter 3 number. If you enter less numbers you see no output.
Some comments:
Your cin.get() doesn't stop execution.
Using std (like using namespace std) and definition own vector class - it's very bad idea.
I was creating a matrix class with overloaded operators in C++, I overloaded operators, << (output, with the ostream library), operator + that adds to matrices, operator = that's is used to assign one matrix to another. The problem is that when I use
cout<<m1+m2<<endl;
I get an error
E0349: No operator << matches these operands type are: std::ostream << Matrix
But if i do the following:
Matrix m = m1 + m2;
cout<<m<<endl;
it works perfect.
Here is the << operator:
ostream& operator<< (ostream &os,const Matrix& m)
{
if (m.isValid())
{
os << '|';
for (int i = 0; i < m.getRows(); i++)
{
for (int j = 0; j < m.getCols(); j++)
{
os << m.getMatrix()[i][j];
if (j < m.getCols() - 1)
{
os << ',';
}
}
os << '|';
}
}
else
{
os << "invalid matrix!";
}
return os;
}
The + operator:
Matrix Matrix::operator+ (Matrix &m)
{
Matrix* answer = new Matrix(m); //allocating space
if (valid && m.valid)//if they are both valid
{
if (colNum == m.colNum&&rowNum == m.rowNum) //if are from same size
{
answer->valid = true; //valid set to be true
for (int i = 0; i < rowNum; i++) //going over the matrix
{
for (int j = 0; j < colNum; j++)
{
answer->matrix[i][j] += matrix[i][j]; //adding data
}
}
}
else
{
//clearing data
delete answer;
answer = new Matrix();
}
}
else
{
//clearing data
delete answer;
answer = new Matrix();
}
return *answer;
}
And the = operator:
Matrix Matrix::operator= (Matrix &m)
{
int rows = m.rowNum; //putting cols and rows from the data
int cols = m.colNum;
if (m.valid)
{
matrix = new int*[rows]; //defining the matrix - first allocatin space for rows
for (int i = 0; i < rows; i++) //now allocating space for cols
{
matrix[i] = new int[cols];
}
for (int i = 0; i < rows; i++) //now going over the matrix and putting the data in
{
for (int j = 0; j < cols; j++)
{
matrix[i][j] = m.matrix[i][j];
}
}
}
//putting the rows and cols data
rowNum = m.rowNum;
colNum = m.colNum;
valid = m.valid; //setting to the right valid type
return *this;
}
and the class variables:
class Matrix
{
private:
bool valid;
int** matrix;
int rowNum;
int colNum;
There is a copy constructor a string constructor and a constructor that gets string input according to an algorithm and transforms it to a matrix.
You are actually faced with the fact that you Can't pass temporary object as reference (the link is to another question here on StackOverflow).
The solution in your case should be to replace:
ostream& operator<< (ostream &os,Matrix& m)
with:
ostream& operator<< (ostream &os,const Matrix& m)
as the overloaded operator signature. You currently expects an lvalue reference, In the case of
Matrix m = m1 + m2;
cout << m << endl;
that is what you're calling the function with m - a named variable and will outlive the execution of the command. In the failing case, you're calling the function with m1+m2 - the result of a plus operation, which is a temporary object. It just doesn't match your overload.
By the way - this change also makes sense because you're not modifying the matrix as you print it - you treat it as const.
This question already has answers here:
My attempt at value initialization is interpreted as a function declaration, and why doesn't A a(()); solve it?
(5 answers)
Understanding 'most vexing parse' - why allow ambiguous syntax?
(2 answers)
Closed 5 years ago.
I have following piece of code
#include <iostream>
using namespace std;
class TestMatrix {
int row, col;
int **arr = NULL;
public:
friend istream& operator>> (istream &in, TestMatrix &mat);
friend ostream& operator<< (ostream &out, TestMatrix &mat);
TestMatrix(int row=1, int col=1):row(row), col(col){
arr = new int*[row];
for (int i = 0; i<row; i++) {
arr[i] = new int[col];
}
}
};
TestMatrix() {
/*cout << "Enter number of rows of your matrix";
cin >> this->row;
cout << "Enter number of columns of matrix";
cin >> this->col;*/
this->row = 3;
this->col = 3;
arr = new int*[this->row];
for (int i = 0; i<this->row; i++) {
arr[i] = new int[this->col];
}
}
istream & operator>> (istream & in, TestMatrix &mat)
{
cout << "Enter " << mat.row * mat.col << " numbers row wise \n";
for (int i = 0; i < mat.row; i++) {
for (int j = 0; j < mat.col; j++) {
in >> mat.arr[i][j];
}
}
return in;
}
ostream & operator<< (ostream & out, TestMatrix &mat) {
for (int i = 0; i < mat.row; i++) {
for (int j = 0; j < mat.col; j++) {
cout << mat.arr[i][j] << " ";
}
cout << "\n";
}
return out;
}
int main() {
TestMatrix mMatrix1(3, 3);
TestMatrix mMatrix2();
//**This works fine
cin >> mMatrix1;
//**This gives error
cin >> mMatrix2;
return 0;
}
I am trying to overload insertion and extraction operator.
I have instantiated class TestMatrix using overloaded constructors.
While trying to access overloaded operator with instance which was constructed using constructor without argument, I get error stating
binary '>>': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion)
Can someone please explain reason for same.
I am currently working on a project implementing a templated matrix class; however, whenever I try to run my test function, the program crashes and core dumps. The following is the output I get:
0 0
[3 3 1 2 3 4 5 6 9 8 10]
[1 2 3
4 5 6
9 8 10]
stream out sucessInvalid Input for matrix
stream in sucessError: matrix Multiplication not defined.
[1 2 3
4 5 6
9 8 10]
Error: The addition of two matrices of different demensions is not defined.
Error: The addition of two matrices of different demensions is not defined.
7700640
7700576
Error: The addition of two matrices of different demensions is not defined.
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00000030143b0778 ***
======= Backtrace: ========= <Continues> ...
The Calling function is:
TestingMatrix(){
matrix<int> a, b, c;
//Three empty matrices are created
cout << a.numrows() << " " << a.numcols() << endl; // yields 0 0
cin >> a; // User types [3 3 1 2 3 6 5 4 9 8 10]
// This will create a 3 by 3 matrix
cout << a;
cin >> b; //User types [3 2 9 1 2 3 4 5]
cout << b;
c=a*b;
cout << c << endl;
cout << b+c << endl;
matrix<int> d(5*b); // d is initialized to 5*b
cout << d << endl;
cout << a[0][0] << endl;
//Should printout 1
cout << a[1][2] << endl;
//Should printout 4
d = a + b;
//This should cause an exception that you
//are able to handle; The sizes of a and b don’t agree.
}//End of TestingMatrix() function
The matrix class is as follows:
// matrix.h
#ifndef matrix_H
#define matrix_H
#include <iostream>
#include <cstdlib>
using namespace std;
template <class mType> class matrix {
public:
matrix() : N(0), M(0), origin(NULL) { /* EMPTY */ }
matrix(int n, int m): N(n), M(m), origin(NULL) {
allocate(n,m);
}
~matrix() {
clear();
}
matrix & operator=(const matrix &rhs) {
if (this != &rhs) { //Check to see they're not the same instance
this->clear();
this->allocate(rhs.numrows(), rhs.numcols());
for(int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
this->origin[i][j] = rhs[i][j];
}
return *this;
}
matrix & operator+=(const matrix &rhs) {
try {
if ( this->numrows() != rhs.numrows() ||
this->numcols() != rhs.numcols() )
throw 1;
}
catch (int e)
{
cerr << "Error: The addition of two matrices of different demensions is not defined." << endl;
return *this;
}
for(int i=0; i<N; ++i)
for (int j=0; j<M; ++j)
this->origin[i][j] += rhs[i][j];
return *this;
}
const matrix operator+(const matrix &rhs) const {
matrix tmp = *this; // tmp copy so we can use the += operator
return (tmp += rhs); // return answer
}
const matrix operator*(const matrix &rhs) const {
try {
if ( this->numcols() != rhs.numrows() )
throw 1;
}
catch (int e)
{
cerr << "Error: matrix Multiplication not defined." << endl;
return *this;
}
matrix<mType> returnmatrix(this->numrows(), rhs.numcols());
for (int i=0; i<returnmatrix.numrows(); ++i)
for (int j=0; j<returnmatrix.numcols(); ++j)
for (int k=0; k < this->numcols(); ++k)
returnmatrix[i][j] += *this[i][k] * rhs[k][j];
return returnmatrix;
}
inline int const numrows() const {
return N;
}
inline int const numcols() const {
return M;
}
void allocate(int n, int m) {
if (origin)
clear();
origin = new mType* [n];
for (int i=0; i<n; ++i)
origin[i] = new mType[m];
M=m;
N=n;
}
void clear() {
if (origin) {
for(int i = 0; i < N; i++)
delete[] origin[i];
delete origin;
}
M=N=0; // Reset
origin=NULL;
}
mType* operator [] (const int index) { return origin[index]; }
const mType* operator [] (const int index) const { return origin[index]; }
friend matrix<mType> operator*( mType factor, const matrix<mType> rhs ) {
matrix<mType> out(rhs.numrows() , rhs.numcols());
for (int i=0; i<rhs.numrows(); ++i) {
for (int j=0; j<rhs.numcols(); ++j) {
out[i][j] = rhs[i][j]*factor;
}
}
return out;
}
friend ostream& operator<< (ostream& out, const matrix<mType>& A) {
if (A.numrows() > 0 && 0 < A.numcols()) {
out <<"[";
for (int j=0; j<A.numcols(); ++j) {
out << A[0][j] << " ";
}
for (int i=1; i<A.numrows(); ++i) {
out << endl;
for (int j=0; j<A.numcols(); ++j) {
out << " " << A[i][j];
}
}
out << "]" <<endl;
}
return out;
}
friend istream& operator>> (istream& in, matrix<mType> &A) {
//[3 2 9 1 2 3 4 5]
//toss first char
try {
if (in.get() != '[')
throw 1;
int N, M;
mType tmp;
in >> N;
in >> M;
A = matrix<mType>(N,M);
for (int i=0; i<N; ++i)
for (int j = 0; j < M; j++)
{
in >> tmp;
A[i][j] = tmp;
}
in.get();
}
catch (int e) {
cerr << "Invalid Input for matrix" << endl;
}
return in;
}
private:
int N, M;
mType ** origin;
};
#endif
Does anyone have any idea as to how resolve this? I'm pretty lost as to the source fo this issue.
Thanks in advance.
Since you have dynamically allocated resources, you should follow the rule of three and implement a copy constructor. Currently a copy construction will use the compiler generated copy constructor, making a copy of the pointer to the underlying data, without copying the data itself.
There is at least one copy construction in your addition operator:
const matrix operator+(const matrix &rhs) const {
matrix tmp = *this; // copy!
return (tmp += rhs); // potentially another copy
}
You have no copy c-tor and compiler will generate default, which does memberwise-copy, but if you have dynamically allocated resources in class - you should have your own copy c-tor, that do deep-copy.
I am trying to overload the ostream << operator in my Matrix class, but I keep getting the following error:
Expected constructor, destructor, or type conversion before token &
Matrix::ostream& operator<<(const Matrix& matrix)
{
for (int r = 0; r < matrix.getNumrows(); r++)
{
cout << matrix.getPoint(r, 0);
for (int c = 0; c < matrix.getNumcolumns(); c++)
{
cout << " " << matrix.getPoint(r,c);
}
cout << endl;
}
return stream;
}
This is the rest of my class
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include "Matrix.h"
using namespace std;
Matrix::Matrix()
{
}
Matrix::Matrix(int rows, int cols) {
numRows=rows;
numCols=cols;
//col=new double[cols];
mx=new double*[rows];
for ( int i=0; i < rows; i++ ) {
mx[i] = new double[cols];
// initalize each element of the new row.
for ( int c=0; c < cols; c++ ) {
mx[i][c] = 0.0;
}
}
}
Matrix::Matrix(const Matrix &theMatrix) {
int rows=theMatrix.numRows;
int cols=theMatrix.numCols;
numRows = rows;
numCols = cols;
mx=new double*[rows];
for ( int r=0; r < rows; r++ ) {
mx[r] = new double[cols];
// copy each element of the new row.
for ( int c=0; c < cols; c++ ) {
mx[r][c] = theMatrix.mx[r][c];
}
}
}
void Matrix::setMatrix(string file)
{
/* read the file */
fstream inputStream(file.c_str());
if(inputStream.is_open() )
{
string line;
stringstream ss;
getline(inputStream, line);
ss.clear();
ss.str(line);
ss >> numRows >> numCols;
mx=new double*[numRows];
for ( int i=0; i < numRows; i++ ) {
mx[i] = new double[numCols];
// initalize each element of the new row.
for ( int c=0; c < numCols; c++ ) {
mx[i][c] = 0.0;
}
}
//now loop to get values
for(int row=0; row<numRows; row++)
{
getline(inputStream, line);
ss.clear();
ss.str(line);
//now get every value in the line
for(int col=0; col<numCols; col++)
{
double current;
ss >> current;
mx[row][col] = current;
}//end reading values of row
}//end reading rows
}
//close the file
inputStream.close();
}
int Matrix::getNumrows()
{
return numRows;
}
int Matrix::getNumcolumns()
{
return numCols;
}
void Matrix::printPoint()
{
for ( int r=0; r < numRows; r++ )
{
for ( int c=0; c < numCols; c++ )
{
cout << mx[r][c] << " ";
}
cout << endl;
}
cout << endl;
}
bool Matrix::getIsSquared()
{
if( numRows == numCols )
{
return true;
}
else
{
return false;
}
}
double Matrix::det()
{
double det=0.0;
if(numRows!=numCols)
{
cout << "Number Rows must be same as number Colums\n";
}
if(numRows==2)
{
det=(mx[0][0]*mx[1][1])-(mx[0][1]*mx[1][0]);
}
else
{
for(int i=0 ; i<numCols ; i++)
{
Matrix temp(numRows-1,numCols-1);
for(int j=0 ; j<numRows-1 ; j++)
{
for(int k=0 ; k<numCols-1 ; k++)
{
if(k<i)
temp.mx[j][k]=mx[j+1][k];
else
temp.mx[j][k]=mx[j+1][k+1];
}
}
det+=pow(-1.0,i)*mx[0][i]*temp.det();
}
}
return det;
}
double Matrix::getPoint(int row, int col)
{
return mx[row][col];
}
Matrix Matrix::operator +(const Matrix &right) const
{
Matrix result(numRows,numCols);
if ( right.numRows != numRows || right.numCols != numCols )
{
cout << "\nError while adding matricies, the two must have the same dimentions.\n";
}
else
{
for ( int r=0; r < numRows; r++ )
{
for ( int c=0; c < numCols; c++ )
{
result.mx[r][c] = (this->mx[r][c]) + (right.mx[r][c]);
}
}
}
return result;
}
If you want to overload the ostream operator<< for your class, you need to use either a friend function or a non-member function because the ostream object appears on the left-hand side of the expression (it's written as os << my_matrix).
std::ostream& operator<<(std::ostream& os, const Matrix& matrix) { /* ... */ }
It looks like you are trying to implement it as a member function, but that should actually look like:
std::ostream& Matrix::operator<<(const Matrix& matrix) { /* ... */ }
This won't work because when you implement an operator overload as a member function, the type of the object on the left hand side of the expression is the same as the type of the class of which the overload is a member (so, in this case, you'd have to write my_matrix1 << my_matrix2, which isn't what you want).
Inside of the overload, you shouldn't write to cout directly; you should write to the ostream object that is passed as an argument to the function.
Write it as:
ostream& operator<<(ostream& os, const Matrix& matrix)
{
for (int r = 0; r < matrix.getNumrows(); r++)
{
os << matrix.getPoint(r, 0);
for (int c = 0; c < matrix.getNumcolumns(); c++)
{
os << " " << matrix.getPoint(r,c);
}
os << endl;
}
return os;
}
and it will work. It does not have to be a member function of Matrix.
Just change
Matrix::ostream& operator<<(const Matrix& matrix)
to
std::ostream& operator<< (std::ostream &stream, const Matrix &matrix)
It'll be a stand-alone function .. and should work just fine.