C++ Operator Overload >> - c++

I hadn't found answer even if exist anywhere.
I have class and I want overload >> operator
That code compile but it don't work how I want.
I want put value in all cells inside array, but it only work for 1st cell. Looks like my loop don't work.
Edited:
Full code below. Btw sorry for language but this is my homework and teacher want that names.
#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
template <class T>
class Wielomian {
private:
int stopien;
T *wspolczynniki;
public:
friend std::ostream & operator << (std::ostream &output, Wielomian &w)
{
output << "Wielomian: ";
for (int i = w.stopien-1; i >= 0; i--)
{
output << w.wspolczynniki[i] << "x^" << i << " ";
if (i)
output << "+ ";
}
return output;
}
friend std::istream & operator >> (std::istream &input, Wielomian &w)
{
int i = 0;
do {
input >> w.wspolczynniki[i++];
} while (w.stopien < i);
return input;
}
T operator () (T x)
{
T wynik = 0;
for (int i = 0; i < this->stopien; i++)
{
wynik += this->wspolczynniki[i] * pow(x,i);
}
return wynik;
}
T& operator[](const int index)
{
return wspolczynniki[index];
}
Wielomian operator + (const Wielomian &w)
{
const Wielomian *wiekszy;
const Wielomian *mniejszy;
if (w.stopien > this->stopien)
{
wiekszy = &w;
mniejszy = this;
}
else
{
wiekszy = this;
mniejszy = &w;
}
for (int i = 0; i < mniejszy->stopien; i++)
wiekszy->wspolczynniki[i] += mniejszy->wspolczynniki[i];
return *wiekszy;
}
Wielomian operator - (const Wielomian &w)
{
const Wielomian *wiekszy;
const Wielomian *mniejszy;
if (w.stopien > this->stopien)
{
wiekszy = &w;
mniejszy = this;
}
else
{
wiekszy = this;
mniejszy = &w;
}
for (int i = 0; i < mniejszy->stopien; i++)
wiekszy->wspolczynniki[i] -= mniejszy->wspolczynniki[i];
return *wiekszy;
}
Wielomian operator = (const Wielomian &w)
{
this->stopien = w.stopien;
this->wspolczynniki = new float[this->stopien];
memcpy(this->wspolczynniki, w.wspolczynniki, w.stopien * sizeof(double));
}
Wielomian(const Wielomian &w)
{
this->stopien = w.stopien;
this->wspolczynniki = new float[this->stopien];
memcpy(this->wspolczynniki, w.wspolczynniki, w.stopien * sizeof(double));
}
Wielomian(int stopien = 0, T wspolczynik[] = { 3 })
{
this->stopien = stopien;
wspolczynniki = new T[this->stopien];
for (int i = 0; i < stopien; i++)
{
this->wspolczynniki[i] = wspolczynik[i];
}
}
~Wielomian()
{
free(this->wspolczynniki);
}
};
int main()
{
double tab[4] = {3,4,5,6};
Wielomian<double> w1(4,tab);
std::cin >> w1;
std::cout << w1;
std::cin.get();
std::cin.get();
return 0;
}

Your while condition in operator >> is wrong. In your code you have:
int i = 0;
do {
input >> w.wspolczynniki[i++];
} while (w.stopien < i);
i is 0 at the beginning, and then after input >> w.wspolczynniki[i++] it is 1. The while condition is (w.stopien < i) so if w.stopien (which is 4 in your example) is smaler then i which is 1 in the first iteration, you will continue the loop. But 4 < 1 is false you will always only read one value.
So get your do-while to work you would need to change it to (w.stopien > i). But as you test if your index i is in the correct range you shouldn't use a do-while at all, but a while loop.
int i = 0;
while (i < w.stopien) {
input >> w.wspolczynniki[i++];
}
Or even a for loop, which would make clearer what you are doing:
for(int i=0; i< w.stopien; i++) {
input >> w.wspolczynniki[i];
}
In addition to that - and what is already mentioned in the comments - never combine the memory allocations and deallocation that don't belong together. If you use new[] then you have to use delete[] to free the memory and not free.
And don't use signed numbers (int) for indices, so stopien and i should be unsigned (e.g. size_t). And for stopien you should ensure on construction that it is 1 or larger.
And if you are allowed to you should switch form T* wspolczynniki to std::vector<T> wspolczynniki that would allow you to get rid of the copy constructor, the assignment operator, the destructor, you would not need int stopien, and you could simplify other parts of the code using [algorithm](https://en.cppreference.com/w/cpp/algorithm), or at least keep that you normally would use astd::vector` (or other containers) then doing the allocation and the copying yourself.

Related

Overloading Operator *= and Operator+ in Matrix Template Class

The method template <class T> const Matrix<T> &Matrix<T>::operator*=(T rhs) for program matrix.cc should be able to returns calling object with matrix scaled by rhs, and the parameter rhs will be the same type as the matrix.
The error output that I am receiving from the compiler is:
[hw7] make clean && make bin/test_matrix_mul_assign && ./bin/test_matrix_mul_assign
rm -f bin/*
g++ -std=c++11 -Wall -I inc -I src -c src/test_matrix_mul_assign.cc -o bin/test_matrix_mul_assign.o
g++ bin/test_matrix_mul_assign.o -o bin/test_matrix_mul_assign
Testing Matrix::operator*=
Expected Matrix[0][0]: 2.0, Actual: 1
FAILED
Could someone let me know why I receive this "Failed" output when I know I pass the // TEST MUL ASSIGMENT OP CORRECT RETURN section.
Here is my matrix.cc:
#include <matrix.h>
template <class T>
const Matrix<T> &Matrix<T>::operator*=(T rhs) {
unsigned int rows_ = 0;
unsigned int cols_ = 0;
T **m_ = nullptr;
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] = m_[i][j] * rhs;
}
}
return *this;
}
template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const {
if (!(this->cols_ == rhs.cols_) && (this->rows_ == rhs.rows_)) {
std::cout << "Cannont add matrices. Wrong dimensions\n";
exit(0);
}
Matrix<T> lhs;
lhs.rows_ = this->rows_;
lhs.cols_ = this->cols_;
for (unsigned int i = 0; i < lhs.rows; ++i) {
for (unsigned int j = 0; j < lhs.cols_; ++j) {
lhs[i] += rhs[i];
}
}
return lhs;
}
Here is my matrix.h:
#include <cassert>
// using assert
#include <exception>
#include <iostream>
template <class T>
class Matrix {
public:
friend class MatrixTester;
/* Times Equals Op: 1 Point
* Returns calling object with matrix scaled by rhs.
* Parameter:
* - rhs will be the same type as the matrix
*/
const Matrix<T> &operator*=(T rhs);
/* Add Op: 1 Point
* Returns the sum of calling object's matrix and rhs's matrix as a new
* object.
* Precondition(s):
* - lhs rows must equal rhs rows
* - lhs cols must equal rhs cols
*/
const Matrix<T> operator+(const Matrix<T> &rhs) const;
private:
T **m_;
unsigned int rows_;
unsigned int cols_;
};
#include <matrix.cc> //NOLINT
This is my test_matrix_mul_assign.cc tester:
#include <test_matrix.h>
int main(int argc, char **argv) {
MatrixTester tester;
cout << "Testing Matrix::operator*=" << endl;
if (tester.Test_MulAssignOp()) {
cout << " PASSED" << endl;
return 0;
}
cout << " FAILED" << endl;
return 1;
}
bool MatrixTester::Test_MulAssignOp() const {
const int kRows = 3, kCols = 4;
Matrix<double> test_m;
test_m.m_ = new double *[kRows];
for (unsigned int i = 0; i < kRows; ++i) {
test_m.m_[i] = new double[kCols];
for (unsigned int j = 0; j < kCols; ++j)
test_m.m_[i][j] = (i + 1.0) * (j + 1.0);
}
test_m.rows_ = kRows;
test_m.cols_ = kCols;
// TEST MUL ASSIGMENT OP CORRECT RETURN
const Matrix<double> *m_ptr = &(test_m *= 2.0);
if (m_ptr != &test_m) {
cout << " Expected return address of assigment: " << &test_m
<< ", Actual: " << m_ptr << endl;
return false;
}
// TEST MUL ASSIGMENT OP CALCULATION
if (test_m.m_[0][0] != 2.0) {
cout << " Expected Matrix[0][0]: 2.0, Actual: " << test_m.m_[0][0] << endl;
return false;
}
if (test_m.m_[1][3] != 16.0) {
cout << " Expected Matrix[1][3]: 16.0, Actual: " << test_m.m_[1][3]
<< endl;
return false;
}
if (test_m.m_[2][2] != 18.0) {
cout << " Expected Matrix[2][2]: 18.0, Actual: " << test_m.m_[2][2]
<< endl;
return false;
}
return true;
}
You have the following variable definitions in the operator*= implementation:
unsigned int rows_ = 0;
unsigned int cols_ = 0;
T **m_ = nullptr;
They will shadow all of the members of the class. When you use rows_, cols_ and m_ later in the function definition they will refer to these local variables, not the class members of the current instance.
Therefore effectively your implementation of operator*= does nothing at all. It is not surprising that the test for the correct value then fails.
Simply remove these declarations, so that the names will refer to the current instance's members instead.
Then there is also not going to be any point to m_[i] = new T[cols_];. So remove that as well.
Why are there all of these dynamic allocations with new in the first place? This is seriously bad style and is going to cause you all kinds of issues. Use std::vector instead.
class Matrix also seems to be lacking a proper constructor. This again will cause all kinds of issues, especially when it leaves memory allocation to a user of the class.

Having a logic error when compiling C++ program that is supposed to represent arbitrarily large numbers as a string

This is actually a homework problem, I've had people be irritated with me before for asking about school stuff but I feel like this is the best place to ask, I appreciate your help in advance!
Instructions:
The Bigint class represents arbitrarily large integers (values larger than can be supported with unsigned long long int data types) as C++ string objects, and supports addition of these values.
At this point, my code is compiling okay, but the output is not at all what I am looking for.
I tried adding a cout statement before the return statement in the add function so I could see what the value of my_return ended up as, but that statement didn't even execute at all. This is my first time using dynamic arrays. Also, this is the second rewrite of the program that is having the same incorrect result.
#include <iostream> // Standard streams
class Bigint
{
public:
// Six Pack
Bigint();
Bigint(std::string);
Bigint(const Bigint &);
Bigint(Bigint &&);
Bigint & operator = (const Bigint &);
Bigint & operator = (Bigint &&);
// Input and output
friend std::ostream & operator << (std::ostream &, const Bigint &);
friend std::istream & operator >> (std::istream &, Bigint &);
Bigint operator + (Bigint) const; // Addition
private:
std::string value;
std::string add(std::string, std::string) const;
};
// Private Member Function
std::string Bigint::add(std::string left, std::string right) const {
int needed_length, left_length, right_length, carry = 0;
int * left_array = NULL;
int * right_array = NULL;
int * sum_array = NULL;
std::string my_return;
left_length = static_cast<int>(left.length());
right_length = static_cast<int>(right.length());
if (left_length > right_length) {
needed_length = left_length;
} else if (left_length < right_length) {
needed_length = right_length;
} else {
needed_length = left_length;
}
left_array = new int[needed_length];
// store left string into left_array backwards
for (int indx = 0; indx < left_length; indx++) {
left_array[indx] = static_cast<int>(left[left_length - 1 -indx]);
}
right_array = new int[needed_length];
// store right string into right_array backwards
for (int indx = 0; indx < right_length; indx++) {
right_array[indx] = static_cast<int>(right[right_length - 1 - indx]);
}
sum_array = new int[needed_length + 1];
for (int indx = 0; indx < needed_length; indx++) {
sum_array[indx] = (left_array[indx] + right_array[indx] + carry) % 10;
if (left_array[indx] + right_array[indx] + carry >= 10) {
carry = 1;
} else {
carry = 0;
}
}
sum_array[needed_length] = carry;
// reverse contents of sum_array and store in a string
for (int indx = 0; indx <= needed_length; indx++) {
my_return[indx] = static_cast<char>(sum_array[needed_length - indx]);
}
delete [] left_array;
delete [] right_array;
delete [] sum_array;
return my_return;
}
// Standard Six Pack
Bigint::Bigint() {
value = ' ';
}
Bigint::Bigint(std::string my_string) {
value = my_string;
}
Bigint::Bigint(const Bigint & other) {
value = other.value;
}
Bigint::Bigint(Bigint && other) {
value = other.value;
}
Bigint & Bigint::operator = (const Bigint & other) {
value = other.value;
return *this;
}
Bigint & Bigint::operator = (Bigint && other) {
value = other.value;
return *this;
}
// Input and Output
std::ostream & operator << (std::ostream & outstream, const Bigint & other) {
for (int indx = 0; indx < static_cast<int>((other.value).length()); indx++) {
outstream << other.value[indx];
}
outstream << std::endl;
return outstream;
}
std::istream & operator >> (std::istream & instream, Bigint & other) {
std::string temp;
instream >> temp;
for (int indx = 0; indx < static_cast<int>(temp.length()); indx++) {
other.value[indx] = temp[indx];
}
return instream;
}
// Arithmetic
Bigint Bigint::operator + (Bigint other) const {
std::string str1, str2;
str1 = value;
str2 = other.value;
Bigint my_return(add(str1, str2));
return my_return;
}
int main()
{
Bigint var_a, var_b;
// Input
std::cout << "Enter two big integers on a line: ";
std::cin >> var_a >> var_b;
// Display result
std::cout << "Sum of " << var_a << " + " << var_b << " = " << var_a + var_b << std::endl;
// All done
return 0;
}
The expected results are as follows:
Enter two big integers on a line: 88999988888 7777777777777777
Sum of 88999988888 + 7777777777777777 = 7777866777766665
Actual results:
Enter two big integers on a line: 88999988888 7777777777777777
Sum of 8
+ 7
=
Program ended with exit code: 0
This is wrong:
std::istream & operator >> (std::istream & instream, Bigint & other) {
std::string temp;
instream >> temp;
for (int indx = 0; indx < static_cast<int>(temp.length()); indx++) {
other.value[indx] = temp[indx];
}
return instream;
}
There is no need for temp and it is also incorrect to use it. It is incorrect because its length will be larger than Bigint::value which is a problem for other.value[indx] (it is larger in main's usage where var_a and var_b each have a length of one)
Instead just do this:
std::istream& operator>>(std::istream& instream, Bigint& other) {
instream >> other.value;;
return instream;
}
Likewise you don't need a loop in friend std::ostream& operator<<(std::ostream&, const Bigint&); either
This is probably not doing what you are expecting:
for (int indx = 0; indx < left_length; indx++) {
left_array[indx] = static_cast<int>(left[left_length - 1 -indx]);
}
For the input "12" "34" the "12" part will be executed by this loop and left_array will have the values 50 and 49 instead of 1 and 2. This is because those are the ASCII values of '1' and '2'
Instead convert like this:
for (int i = 0; i < left_length; i++)
left_array[i] = left[left_length - 1 - i] - '0';
Subtracting by '0' has the effect of subtracting 48. Converting to int is automatic, no need for the cast
Likewise the conversion back needs to change:
for (int indx = 0; indx <= needed_length; indx++) {
my_return[indx] = static_cast<char>(sum_array[needed_length - indx]);
}
my_return has a length of zero when it is being written to so the first thing to do is resize it. Then you can write each character by doing the reverse of the previous conversion. Also the indexing was off by one
Changed:
my_return.resize(needed_length);
for (int i = 0; i < needed_length; i++)
my_return[i] = static_cast<char>(sum_array[needed_length - i - 1] + '0');

Ostream operator overload not working

I am having issues with the ostream operator overload. When I cout in my Main() it outputs
/ c"\progra"
Why it is outputting the file path and not the stream I created, I can not figure out. I am omitting the code that is not part of outputting the array. I am trying to loop through each element of the array and add it to a string that is in the end outputted via cout;
Main.cpp
Search test(20);
test.init_sorted();
cout << test;
Search.cpp
Search::Search(int size)
{
array_size = size;
numbers = new int[size];
}
void Search::init_sorted()
{
for (int i = 0; i < array_size; i++) {
if (i == 0) {
srand(for_srand);
numbers[i] = rand() % 5;
}
else {
srand(for_srand);
numbers[i] = numbers[i - 1] + rand() % 5;
}
}
}
ostream & operator<<(ostream & os, const Search & s)
{
string output;
for (int i = 0; i < s.array_size; i++) {
output += s.numbers[i] + " / ";
}
os << output;
return os;
}
Search.h
class Search
{
private:
int array_size;
int *numbers;
int for_srand = 10;
public:
Search(int);
~Search();
friend ostream& operator<<(ostream& os, const Search& dt);
};
Undefined behaviour. Due to pointer arithmetic,
output += s.numbers[i] + " / ";
is the same as
output += " / "[s.numbers[i]];
Also, it's not going to format any number:
for (int i = 0; i < s.array_size; i++) {
out << s.numbers[i] << " / ";
}
That being said, unless you know what you're doing, use standard containers and algorithms, e.g. std::vector<int> instead of int*.

Addition of 2D Dynamic Arrays

I have a class project that is to make and operate on dynamic objects.
I have a class called Matrix that uses a 2 dimensional pointer array to store object of type Complex (which is a complex number class). I need to be able to add 2 arrays by adding all of the values in the arrays together and returning a new array. The issue is that I don't understand the syntax for accessing each Complex object in the array. Here is what I have so far for the overloaded addition operator:
const Matrix Matrix::operator+(const Matrix& rhs) const
{
Matrix newMatrix(mRows,mCols);
for(int i=0;i<mRows;i++)
{
for(int j=0;j<mCols;j++)
{
(*newMatrix.complexArray[i]) = (*complexArray[i])+ (*rhs.complexArray[i]);
}
}
return newMatrix;
}
Here is the overloaded input operator for the Matrix object:
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+matrix.mCols);i++)
{
Complex* newComplex = new Complex();
input >> *newComplex;
matrix.complexArray[i] = newComplex;
}
}
return input;
}
Here is the Matrix class definition:
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;
Complex **complexArray;
public:
Matrix(int=0,int=0);
Matrix(Complex&);
~Matrix();
Matrix(Matrix&);
Matrix& operator=(const Matrix&);
const Matrix operator+(const Matrix&) const;
};
And the constructor:
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 Complex[mRows];
complexArray= new Complex*[mRows];
for(int i=0;i<mRows;i++)
{
complexArray[i] = new Complex[mCols];
}
}
}
As it is now, the program compiles, but stops working when it gets to the addition of matrices during runtime. If anyone can tell me what syntax I should be using and why, it would be extremely helpful.
You don't seem to be taking in enough input. You're taking (rows+cols) complex numbers as input but then attempting (correctly) to iterate over (rows*cols) elements within the matrix.
for(int i=0;i< (matrix.mRows+matrix.mCols);i++)
versus
for(int i=0;i<mRows;i++)
{
for(int j=0;j<mCols;j++)

Dynamic Array print function

In this post
https://codereview.stackexchange.com/questions/5745/dynamic-array-improvements-0
What does this mean? Sorry if the question is vague..I just need to update my print_array function. Full code is below..for my poor man's dynamic array.
Can someone tell me how the overloaed << function works?
// My Current Print Array
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
If you are going to write print_array at least write it so that it can use alternative
stream (not just std::cout). Then write the output operator.
// SO user advice
std::ostream& operator<<(std::ostream& stream, dynamic_array const& data)
{
data.print_array(stream); // After you fix print_array
return stream;
}
// My Dynamic Array Class
#include "c_arclib.cpp"
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
public:
int size;
dynamic_array(int sizein)
{
size=sizein;
array = new T[size]();
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
void merge_recurse(int left, int right)
{
if(right == left + 1)
{
return;
}
else
{
int i = 0;
int length = right - left;
int midpoint_distance = length/2;
int l = left, r = left + midpoint_distance;
merge_recurse(left, left + midpoint_distance);
merge_recurse(left + midpoint_distance, right);
for(i = 0; i < length; i++)
{
if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
{
scratch[i] = array[l];
l++;
}
else
{
scratch[i] = array[r];
r++;
}
}
for(i = left; i < right; i++)
{
array[i] = scratch[i - left];
}
}
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
return 1;
}
else
{
return 0;
}
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
void quick_sort()
{
quick_recurse(0,size);
}
void rand_to_array()
{
srand(time(NULL));
int* k;
for (k = array; k != array + size; ++k)
{
*k=rand();
}
}
};
int main()
{
dynamic_array<int> d1(10);
cout << d1.size;
d1.print_array();
d1.rand_to_array();
d1.print_array();
d1.merge_sort();
d1.print_array();
}
~
~
From your example, whenever operator << is matched between std::ostream& stream and dynamic_array const& data compiler will invoke:
std::ostream& operator<<(std::ostream& stream, dynamic_array const& data)
{
data.print_array(stream); // After you fix print_array
return stream;
}
which behaves like a global operator. In other words, calling:
dynamic_array<int> d(10);
cout << d;
// above is logically equivalent to:
// operator<<(std::cout, d)
Note that the operator<< function returns std::ostream&. That is because we want to be able to chain operator calls:
dynamic_array<int> d(10);
cout << "Data:" << d;
// above is logically equivalent to:
// operator<<( operator<<(std::cout, "Data:"), d);
Since you are using templates to output your array, the stream you are outputing to must know how to interpret the template type. In the example here we are using integers, and there is a predefined operator for that:
std::ostream& operator<<(std::ostream& stream, int const& i);
The only think left to change is like Joshua suggested to modify your print_array function to use ostream& rather than predefined cout.
If you want your function to be able to print to ostreams other than cout, you would do it like this
//i added a default argument of cout, so you don't have to specify
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++)
os << array[i] << endl;
}
The operator<<() function can be explained as follows: it returns a reference to an ostream object, which is the class that cout is a part of. Returning a reference allows for chaining. Now, since operator<<() is not a member function, the first argument is the left side of the operator, in many cases, it would be cout. The second argument is the right side of the operator. And I don't think that is valid C++ syntax, it should be const dynamic_array &data.