Ostream operator overload not working - c++

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*.

Related

C++ Operator Overload >>

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.

Error with dynamic memory

I am trying to use the dynamic memory method instead of the vector method to add elements. Initially, the maximum size of the dynamic memory is set to 5. However, as soon as I try to increase more than the capacity of the current the dynamic memory, the elements of the 0th or 1st index loss their references.
The program works fine if I do not specify the size of the dynamic memory,
like: dynamic_memory = new int;. I am wondering why they lose their references
with the resize of the dynamic memory to more than the initial capacity.
PS: I am using Code::Block 16.01
Here is my program.
#include <iostream>
#include <cstdlib>
using namespace std;
class DynamicVector
{
public:
DynamicVector();
virtual ~DynamicVector();
void insertElement(int input);
int showCapacity();
int showSize();
void doubleSize(int * dynamic_memory);
friend ostream& operator << (ostream& outs, const DynamicVector obj);
private:
int * dynamic_memory;
int max_count; // this is similar to the capacity of the vector
int current_count; // this is similar to size of a vector
};
DynamicVector::DynamicVector()
{
max_count = 5;
dynamic_memory = new int[max_count];
current_count = 0;
}
DynamicVector::~DynamicVector()
{
delete [] dynamic_memory;
}
int DynamicVector::showCapacity(){
return max_count;
}
void DynamicVector::insertElement(int input)
{
if (current_count >= max_count)
doubleSize(dynamic_memory);
dynamic_memory[current_count] = input;
current_count++;
}
void DynamicVector::doubleSize(int * dynamic_memory){
int * tmp = new int[max_count];
for (int i = 0; i < max_count; i++)
tmp[i] = dynamic_memory[i];
delete [] dynamic_memory;
max_count = max_count * 2;
dynamic_memory = new int[max_count];
for (int i = 0; i < max_count; i++)
dynamic_memory[i] = tmp[i];
delete [] tmp;
}
int DynamicVector::showSize(){
return current_count;
}
ostream& operator <<(ostream& outs, const DynamicVector obj)
{
for (int i = 0; i < obj.current_count; i++)
outs << obj.dynamic_memory[i] << endl;
return outs;
}
int main()
{
DynamicVector v;
int numberOfIntendedElement = 11;
cout << "Previously, the capacity of vector was: " << v.showCapacity() << endl;
for (int i = 0; i < numberOfIntendedElement; i++)
v.insertElement(i);
cout << "The capacity of the new vector is: " << v.showCapacity() << endl;
cout << "The size of the new vector is: " << v.showSize() << endl;
cout << "The values in the dynamic vector are: \n" << v << endl;
return 0;
}
Result:
41107976
42075512
2
3
4
5
6
7
8
9
10
In
void doubleSize(int * dynamic_memory);
the dynamic_memory defined here shadows the member dynamic_memory; for comedic hi-jinks and undefined behaviour.
The local dynamic_memory is re-pointed at the new buffer, but the member dynamic_memory continues to point at the deleted original address after the function exits. This means that all subsequent inserts go into invalid memory, and Crom only knows what will happen after that.
Solution
Pass in nothing and use the member variable. Redefine the function as
void doubleSize();
Other problems are addressed in the comments and need to be fixed.
Thank you all for your valuable comments and suggestions, especially user4581301 for pointing a comedic hijinks and undefined behavior. After I redefined the function as void doubleSize(), it worked fine. Here is my final working code.
#include <iostream>
#include <cstdlib>
using namespace std;
class DynamicVector
{
public:
DynamicVector();
virtual ~DynamicVector();
void insertElement(int input);
int showCapacity();
int showSize();
void doubleSize();
friend ostream& operator << (ostream& outs, const DynamicVector obj);
private:
int * dynamic_memory;
int max_count; // this is similar to the capacity of the vector
int current_count; // this is similar to size of a vector
};
DynamicVector::DynamicVector()
{
max_count = 5;
dynamic_memory = new int[max_count];
current_count = 0;
}
DynamicVector::~DynamicVector()
{
delete [] dynamic_memory;
}
int DynamicVector::showCapacity(){
return max_count;
}
void DynamicVector::insertElement(int input)
{
if (current_count >= max_count)
doubleSize();
dynamic_memory[current_count] = input;
current_count++;
}
void DynamicVector::doubleSize(){
int * tmp = new int[max_count];
for (int i = 0; i < max_count; i++)
tmp[i] = dynamic_memory[i];
delete [] dynamic_memory;
max_count = max_count * 2;
dynamic_memory = new int[max_count];
for (int i = 0; i < max_count/2; i++)
dynamic_memory[i] = tmp[i];
delete [] tmp;
}
int DynamicVector::showSize(){
return current_count;
}
ostream& operator <<(ostream& outs, const DynamicVector obj)
{
for (int i = 0; i < obj.current_count; i++)
outs << obj.dynamic_memory[i] << endl;
return outs;
}
int main()
{
DynamicVector v;
int numberOfIntendedElement = 11;
cout << "Previously, the capacity of vector was: " << v.showCapacity() << endl;
for (int i = 0; i < numberOfIntendedElement; i++)
v.insertElement(i);
cout << "The capacity of the new vector is: " << v.showCapacity() << endl;
cout << "The size of the new vector is: " << v.showSize() << endl;
cout << "The values in the dynamic vector are: \n" << v << endl;
return 0;
}
Output
Previously, the capacity of vector was: 5
The capacity of the new vector is: 20
The size of the new vector is: 11
The values in the dynamic vector are:
0
1
2
3
4
5
6
7
8
9
10

Setting an array of bits

I'm writing a program for my OO class and I'm having some trouble with my cout statements. The program is supposed to take in a value and convert it to a bitwise array. My problem is that no matter what number I put in it couts every element in the array to 0. The assignment said to initialize every element to 0 in the constructor, but when comparing it to the & operator in the Query function it can only return false. Any suggestions? (Note: we can't use vectors or any of the premade functions.)
in header file:
private:
static const CSIZE = 8 * sizeof(char);
int arraySize;
unsigned char* barray;
in .cpp file
#include <iostream>
#include "bitarray.h"
using namespace std;
ostream& operator<< (ostream& os, const BitArray& a)
{
for (unsigned int i = 0; i < a.arraySize * a.CSIZE; i++)
os << a.Query(i);
return os;
}
BitArray::BitArray(unsigned int n)
{
if (n % CSIZE != 0)
arraySize = (n / CSIZE) + 1;
else
arraySize = n / CSIZE;
barray = new unsigned char[arraySize];
for (int i = 0; i < arraySize; i++)
barray[i] = 0;
}
unsigned char BitArray::Mask (unsigned int num) const
{
return (1 << num % CSIZE);
}
void BitArray::Set (unsigned int index)
{
unsigned int i = index / CSIZE;
barray[i] |= Mask (index);
}
bool BitArray::Query (unsigned int index) const
{
unsigned int i = index / CSIZE;
if (barray[i] & Mask (index))
return true;
return false;
}
Main program:
#include <iostream>
using namespace std;
#include "sieve.h"
#include "bitarray.h"
int main()
{
unsigned int i, max, counter = 0;
cout << "\nEnter a positive integer for the maximum value: ";
cin >> max;
BitArray ba(max);
Sieve(ba); // find the primes (marking the bits)
cout << "The bit array looks like this: \n"
<< ba
<< '\n';
cout << "\nPrimes less than " << max << ':' << '\n';
for (i = 0; i < max; i++)
{
if (ba.Query(i))
{
counter++;
cout << i;
if (counter % 8 == 0)
{
cout << '\n';
counter = 0;
}
else
cout << '\t';
}
}
cout << "\nGoodbye!\n";
return 0;
}

Using loops to output boxes

My code for outputting boxes, outputs only spaces.
#include <iostream>
using namespace std;
class box{
int x, y;
public:
box(int i, int j){ x = i; y = j; }
friend ostream &operator<<(ostream &stream, box o);
};
ostream &operator<<(ostream &stream, box o)
{
register int i, j;
for (i = 0; i < o.x; i++)
stream << "*";
stream << "\n";
for (j = 1; j < o.y-1; j++){
for (i = 0; i < o.x; i++)
if (i == 0 || i == o.x - 1) stream << "*";
else stream << " ";
stream << "\n";
}
for (i = 0; i < o.x; i++)
stream << "*";
stream << "\n";
return stream;
}
int main(){
box a(14, 6), b(30, 7), c(40, 5);
cout << a << b << c;
return 0;
}
This is supposed to output some boxes made of *
but the only thing it does is create some newlines and spaces.
It doesn't even print box b or box c
EDIT : i found the mistake and corrected it , thanks to everyone
I think that instead of
box(int i, int j){ i = x; j = y; }
you mean
box( int i, int j ) : x( i ), y( j ) {}
And it is better to declare the operator like
friend ostream &operator<<(ostream &stream, const box &o);

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.