Dynamic Array print function - c++

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.

Related

Polynomial Class Project Problem with Division and Destructor C++

This is a project for my object oriented programming class. I need to introduce the followings: overloading + to sum two polynomials, overloading * to multiply a polynomial with a scalar or to multiply it with another polynomial, overloading [] to return coeficient on a specific position, method for adding , deleting a coeficient and evaluating polynom in a certain point (f(x)).
1.Everything is working besides the destructor. The destructor that should be used (delete [] coef) of Polynomial will break (Heap Coruption) if i use cout << A + B and i do not know why.
What i use right now is a workaround but it will not delete coef[0]. That's the point where it breaks. If you can help me somehow i will be gratefull. Can you understand what caused it?
2.I need to have one more overloaded operator, " / ". It should make division between two polynomials and I do not know how to implement it. I tried to search for it but i couldn't understand any algorithm. Any advice or algorithm explanation would be great, because i really do not know from where to start and i need to finish it until tommorrow morning.
3.If you have any advice on coding or efficienty will also be great ( project requirement: do not use STL ).
Thank you!
Polynomial.h:
#pragma once
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::ostream;
using std::istream;
class Polynomial
{
unsigned int deg;
double *coef;
public:
Polynomial() : deg(1), coef(new double[1]) {}
Polynomial(double [], int);
Polynomial(Polynomial&);
Polynomial& operator = (const Polynomial&);
~Polynomial();
friend ostream &operator <<(ostream&, const Polynomial&);
friend istream &operator >>(istream&, Polynomial&);
Polynomial operator + (const Polynomial) ;
double operator[] (unsigned int) const;
Polynomial operator * (int) const;
Polynomial operator * (const Polynomial obj) const;
unsigned int getDeg() { return this->deg; };
double eval(int);
void addCoef(double, int);
void delCoef(int);
};
inline Polynomial::Polynomial(double coefficients[], int number) : deg(number), coef(new double[number])
{
for (int i = 0; i < deg; i++) {
coef[i] = coefficients[i];
}
}
inline Polynomial::Polynomial(Polynomial &ob) {
this->deg = ob.deg;
this->coef = new double[deg];
for (int i = 0; i <= deg; i++)
{
this->coef[i] = ob.coef[i];
}
}
inline Polynomial::~Polynomial() {
for (int i = this->deg; i > 0; i--)
this->delCoef(i);
this->coef[0] = 0; //If i write it like this delete [] coef; it breaks.
this->deg = 0; //with HeapCoruption detected
}
Polynomial.cpp:
Polynomial& Polynomial::operator = (const Polynomial& obj)
{
if (this != &obj) //Testing to avoid situations like A = A;
{
this->deg = obj.deg;
for (int i = 0; i <= obj.deg; i++)
this->coef[i] = obj.coef[i];
}
return *this;
}
istream& operator >> (istream& in, Polynomial& obj)
{
in >> obj.deg;
cout << endl;
obj.coef = new double[obj.deg];
for (int i = 0; i <= obj.deg; i++)
{
in >> obj.coef[i];
}
return in;
}
ostream& operator << (ostream& out, const Polynomial& obj)
{
out << obj.deg << endl;
for (int i = 0; i <= obj.deg; i++)
{
if (obj.coef[i] != 0)
{
if (obj.coef[i] < 0)
out << '(' << obj.coef[i] << ')';
else
out << obj.coef[i];
if (i > 1)
out << "*x^" << i;
if (i == 1)
out << "*x";
if (i != obj.deg)
out << " + ";
}
}
out << endl <<endl;
return out;
}
Polynomial Polynomial::operator+ (const Polynomial obj)
{
Polynomial aux;
if (obj.deg >= deg)
{
aux.deg = obj.deg;
aux.coef = new double[obj.deg];
for (int i = 0; i <= deg; i++)
aux.coef[i] = obj.coef[i] + coef[i];
for (int i = deg + 1; i <= obj.deg; i++)
aux.coef[i] = obj.coef[i];
}
else // obj.deg < this->deg
{
aux.deg = deg;
aux.coef = new double[deg];
for (int i = 0; i <= obj.deg; i++)
{
aux.coef[i] = obj.coef[i] + coef[i];
}
for (int i = obj.deg + 1; i <= deg; i++)
{
aux.coef[i] = coef[i];
}
}
return aux;
}
double Polynomial::operator[] (unsigned int pos) const
{
if (pos > this->deg) {
throw std::out_of_range("Index bigger than polynomial length");
}
return this->coef[pos];
}
Polynomial Polynomial::operator * (const int scalar) const
{
Polynomial aux;
aux.deg = this->deg;
aux.coef = new double[aux.deg];
for (int i = 0; i <= aux.deg; i++)
aux.coef[i] = this->coef[i] * scalar;
return aux;
}
Polynomial Polynomial::operator * (const Polynomial obj) const
{
Polynomial aux;
aux.deg = obj.deg + this->deg;
aux.coef = new double[aux.getDeg()];
for (int i = 0; i <= aux.getDeg(); i++)
aux.addCoef(0, i);
for (int i = 0; i <= this->deg; i++)
for (int j = 0; j <= obj.deg; j++)
aux.coef[i+j] += (this->coef[i]) * obj.coef[j];
return aux;
}
double Polynomial::eval(int x) {
double sum = 0;
for (int i = 0; i <= this->deg; i++)
{
if (i == 0)
sum += this->coef[0];
else
{
int aux = i;
int xaux = x;
aux--;
while (aux != 0)
{
xaux *= x;
aux--;
}
sum += this->coef[i] * xaux;
}
}
return sum;
}
void Polynomial::addCoef(double NewCoef, int pos)
{
if (pos < 0)
return;
if (pos > this->deg)
{
double *newCoef = new double[pos];
for (int i = 0; i <= this->deg; i++)
newCoef[i] = this->coef[i];
for (int i = this->deg + 1; i < pos; i++)
newCoef[i] = 0;
newCoef[pos] = NewCoef;
this->coef = newCoef;
this->deg = pos;
return;
}
else
{
this->coef[pos] = NewCoef;
}
}
void Polynomial::delCoef(int pos)
{
if (pos > this->deg || pos < 0 )
return;
if (pos == this->deg)
{
this->coef[pos] = 0;
int degNoua = pos - 1;
while (this->coef[pos] == 0 && pos != 0)
pos--;
if (pos == 0 && this->coef[pos] == 0)
{
delete this->coef;
this->deg = 0;
}
else
{
this->deg = pos;
double *aux = new double[pos];
for (int i = 0; i <= pos; i++)
aux[i] = this->coef[i];
this->coef = aux;
}
}
else
{
this->coef[pos] = 0;
}
}

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.

Invalid allocation runtime error

I have to replicate a vector class using an int and overload a bunch of operators. How ever every time I try to use the +, -, or / operator I get a runtime error which says invalid allocation size: 4294967295 bytes. Any feed back on how I can improve my code is welcome as well.
my code:
myArray.h
#include<iostream>
using namespace std;
class myArray{
private:
int *A;
int lenght;
int maxSize;
public:
myArray(){lenght = 0; maxSize = 0; A = new int[maxSize];}
myArray(int s){maxSize = s; lenght = 0; A = new int[maxSize];}
myArray(const myArray &M);
~myArray(){delete[] A;}
const int getMaxSize(){return maxSize;}
const int getLenght(){return lenght;}
const myArray& operator +(const myArray& A);
const myArray& operator -(const myArray A);
const int operator *(const myArray& A);
const myArray& operator /(const myArray A);
const myArray& operator +(int A);
const myArray& operator -(int A);
const int operator *(int A);
const myArray operator /(int A);
const myArray operator ++();
const myArray operator ++(int);
const myArray operator --();
const myArray operator --(int);
myArray operator -();
int operator [](int ind) const;
myArray& operator =(const myArray& rho);
void push(int n);
int pop();
void insert(int n, int pos);
int remove(int pos);
void resize(int newSize);
};
myException.h
#include<iostream>
#include<exception>
#include<string>
using namespace std;
class myException: public exception
{
private:
int code;
string reason;
public:
myException(){code = 0; reason = "Unknown";}
myException(int c, string r){code = c; reason = r;}
friend ostream& operator <<(ostream& outputStream, const myException A);
};
ostream& operator <<(ostream& outputStream, const myException A)
{
outputStream << "Code: " << A.code << " Reason: " << A.reason << endl;
return outputStream;
}
myArray.cpp
#ifndef MYARRAY_H
#define MYARRAY_H
#include "myArray.h"
#include "myException.h"
//Copy contructor
myArray::myArray(const myArray &M)
{
maxSize = M.maxSize;
lenght = M.lenght;
A = new int[maxSize];
for(int i = 0; i < M.lenght; i++)
A[i] = M.A[i];
}
//Adds the elements of the array with each other and returns the result
const myArray& myArray::operator +(const myArray& secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = A[i] + secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Subtracts the elements of the array with each other and returns the result
const myArray& myArray::operator -(const myArray secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = this->A[i] - secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Gets the dot product of 2 vectors
const int myArray::operator *(const myArray& secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
int result = 0;
for(int i = 0; i < lenght;i++)
result += this->A[i] * secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Divides the elements of the array with each other and returns the result
const myArray& myArray::operator /(const myArray secondArray)
{
try
{
if(lenght != secondArray.lenght)
throw myException(10, "Different sizes!");
myArray result(secondArray);
for(int i = 0; i < lenght;i++)
result.A[i] = this->A[i] / secondArray.A[i];
return result;
}
catch(myException& e)
{
cout << e;
}
}
//Adds the elements of the array with an int and returns the result
const myArray& myArray::operator +(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] + A;
return result;
}
//Subtracts the elements of the array with an int and returns the result
const myArray& myArray::operator -(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] - A;
return result;
}
//Gets the dot product of a vector multiplied by an int
const int myArray::operator *(int A)
{
int result = 0;
for(int i = 0; i < lenght;i++)
result += this->A[i] * A;
return result;
}
//Divides the elements of the array with an int and returns the result
const myArray myArray::operator /(int A)
{
myArray result(*this);
for(int i = 0; i < lenght;i++)
result = this->A[i] / A;
return result;
}
//increments every element in the array by 1(Pre-increment)
const myArray myArray::operator ++()
{
for(int i = 0; i < lenght; i++)
++A[i];
return *this;
}
//increments every element in the array by 1(Post-increment)
const myArray myArray::operator ++(int)
{
myArray temp(maxSize);
for(int i = 0; i < lenght; i++)
temp.A[i] = A[i]++;
return temp;
}
//decrements every element in the array by 1(Pre-decrement)
const myArray myArray::operator --()
{
for(int i = 0; i < lenght; i++)
--A[i];
return *this;
}
//decrements every element in the array by 1(Post-decrement)
const myArray myArray::operator --(int)
{
myArray temp(maxSize);
for(int i = 0; i < lenght; i++)
temp.A[i] = A[i]--;
return temp;
}
//Makes every element in the array negative
myArray myArray::operator -()
{
for(int i = 0; i < lenght; i++)
A[i] = -A[i];
return *this;
}
//returns the number in the array using []
int myArray::operator [](int ind) const
{
try
{
if(ind > lenght)
throw myException(60, "Array index out of bounds");
return A[ind];
}
catch(myException& e)
{
cout << e;
}
}
//Assignment operator
myArray& myArray::operator=(const myArray& B)
{
delete [] A;
A = new int[B.maxSize];
lenght = B.lenght;
maxSize = B.maxSize;
for(int i = 0; i < B.lenght; i++)
{
A[i] = B.A[i];
}
return (*this);
}
//pushes the value inserted to the next available spot in the array
void myArray::push(int n)
{
try
{
if(lenght == maxSize)
throw myException(30, "Not enough space");
if(lenght == 0)
{
A[0] = n;
lenght++;
}
else
{
for(int i = 0; i < lenght; i++)
{
if(i+1 == lenght)
{
A[i+1] = n;
lenght++;
break;
}
}
}
}
catch(myException& e)
{
cout << e;
}
}
//Removes the last element in the array and returns it
int myArray::pop()
{
try
{
if(lenght <= 0)
throw myException(60, "Array index out of bounds");
int temp = A[lenght - 1];
A[lenght - 1] = NULL;
lenght--;
return temp;
}
catch(myException& e)
{
cout << e;
}
}
inserts an element at the specified position
void myArray::insert(int n, int pos)
{
try
{
if(pos > lenght)
throw myException(60, "Array index out of bounds");
for(int i = 0; i <= lenght; i++)
{
if(i == pos)
{
A[i-1] = n;
}
}
}
catch(myException& e)
{
cout << e;
}
}
//removes an element at a specified position an returns the value.
int myArray::remove(int pos)
{
try
{
if(pos < 0 || (pos > lenght -1))
throw myException(50, "Invalid Position");
int temp = A[pos];
A[pos] = NULL;
for(int i = pos; i < lenght; i++)
{
A[i] = A[i+1];
}
return temp;
}
catch(myException& e)
{
cout << e;
}
}
//Re sizes the entire array
void myArray::resize(int newSize)
{
int *B;
B = new int[newSize];
maxSize = newSize;
for(int i = 0; i < lenght; i++)
B[i] = A[i];
delete[] A;
A = B;
}
#endif
This is just a dummy main to test everything on the myArray class
main.cpp
#include "myArray.h"
int main()
{
int num;
myArray vector1;
myArray vector2(5);
myArray vector3;
vector1.resize(5);
//cout << "Max Size: " << vector1.getMaxSize() << endl;
for(int i = 0; i < 4; i++)
{
cin >> num;
vector1.push(num);
}
for(int i = 0; i < 4; i++)
{
cin >> num;
vector2.push(num);
}
vector3 = vector1 + vector2;
for(int i = 0; i < 4; i++)
cout << vector3.pop() << endl;
}
You create dynamic array with zero size in default constructor.
But in push method you try to set value to it if it's length is zero.
In C++ standard it says:
The effect of dereferencing a pointer returned as a request for zero
size is undefined.
You can only delete it. Fix your push method

Implementing a sort class using templates

I posted last night about an array class, and now I'm having trouble with a sorting class. About half of the functions are defined, either by the professor or by the algorithms he gave us, but a lot of the definitions are confusing me. I'm not sure what makes them any different from the ones above it.
#ifndef SORTS_H
#define SORTS_H
#include <iostream>
#include <string>
#include "Array.h"
using namespace std;
template <class T>
void insertionSort(Array<T> &a);
template <class T>
void selectionSort(Array<T> &a);
template <class T>
void selectionSort(T a[], int n);
template <class T>
void mergesort(T *input, int size);
template <class T>
void mergesort(T *input, int left, int right, T *scratch);
template <class T>
T less(T x, T y);
template <class T>
void mergesort(Array<T> &input, int left, int right, Array<T>&scratch);
template <class T>
void mergesort(Array<T> & input);
Array<int> & random(int n);
template <class T>
void selectionSort(T a[], int n) {
int i, j, tmp;
int min_idx = 0;
for (size_t i = 0; i < n-1; i++) {
min_idx = i;
for (size_t j = i+1; j < n; j++) {
if (a[j] < a[min_idx]) {
min_idx = j;
}
tmp = a[i];
a[i] = a[min_idx];
a[min_idx] = tmp;
}
}
}
template <class T>
void selectionSort(Array<T> &a) {
int tmp;
int min_idx = 0;
for (int i = 0; i < a.getSize() - 1; i++) {
min_idx = i;
for (int j = i + 1; j < a.getSize(); j++) {
if (a[j] < a[min_idx]) {
min_idx = j;
}
tmp = a[i];
a[i] = a[min_idx];
a[min_idx] = tmp;
}
}
}
template <class T>
void insertionSort(Array<T> &a) {
// put your code here
}
template <class T>
bool sorted(Array<T> a) {
for (int i = 1; i < a.getSize(); i++)
if (a[i - 1] > a[i]) return false;
return true;
}
Array<int> & random(int n) {
Array<int> *tmp = new Array<int>(n);
for (int i = 0; i < n; i++)
(*tmp)[i] = rand() % 1000;
return *tmp;
}
template <class T>
T less(T x, T y) {
if (x < y) {
return x;
}
else {
return y;
}
}
template <class T>
void mergesort(T *input, int left, int right, T *scratch) {
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;
mergesort(input, left, left + midpoint_distance, scratch);
mergesort(input, left + midpoint_distance, right, scratch);
/* merge the arrays together using scratch for temporary storage */
for (i = 0; i < length; i++) {
/* Check to see if any elements remain in the left array; if so,
* we check if there are any elements left in the right array; if
* so, we compare them. Otherwise, we know that the merge must
* use take the element from the left array */
if (l < left + midpoint_distance &&
(r == right || min(input[l], input[r]) == input[l])) {
scratch[i] = input[l];
l++;
}
else {
scratch[i] = input[r];
r++;
}
}
/* Copy the sorted subarray back to the input */
for (i = left; i < right; i++) {
input[i] = scratch[i - left];
}
}
}
template <class T>
void mergesort(T *input, int size) {
int *scratch = new int[size];
mergesort(input, 0, size, scratch);
delete [] scratch;
}
template <class T>
void mergesort(Array<T> &input, int left, int right, Array<T>&scratch) {
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;
mergesort(input, left, left + midpoint_distance, scratch);
mergesort(input, left + midpoint_distance, right, scratch);
/* merge the arrays together using scratch for temporary storage */
for (i = 0; i < length; i++) {
/* Check to see if any elements remain in the left array; if so,
* we check if there are any elements left in the right array; if
* so, we compare them. Otherwise, we know that the merge must
* use take the element from the left array */
if (l < left + midpoint_distance &&
(r == right || min(input[l], input[r]) == input[l])) {
scratch[i] = input[l];
l++;
}
else {
scratch[i] = input[r];
r++;
}
}
/* Copy the sorted subarray back to the input */
for (i = left; i < right; i++) {
input[i] = scratch[i - left];
}
}
}
template <class T>
void mergesort(Array<T> &input) {
// put your code here
}
#endif
I also noticed that there is a void insertionSort(Array<T> &a); function, but the algorithm I was given is:
void insertionSort(int a[], int n){
int tmp;
int i, j;
for (i = 1; i < n; i++) {
tmp = a[i];
for (j = i - 1; j >= 0; j--)
if (a[j] > tmp) a[j + 1] = a[j];
else break;
a[j + 1] = tmp;
}
}
Am I supposed to implement this the same way, just replacing int a[] with, say... &arr? I'm guessing since this includes array.h and the array class has T * arr;, I should be pointing to the address of that array? Would this also work for each definition that has the address operator in its parameter?
The difference is one, as you say, takes a typical int array a[], but how would you know the size? So this version requires the user to send it to the function with n as the number of elements. In your Array class you provide a size so there's no need for it. In general you're providing overloads for multiple situations.
I'm not sure what you mean by replacing int a[] w/ &arr, the signature is there, use what was given to you unless you're supposed to change it.
If you go back to your question about the Array class you can see an answer which uses the reference just as you would normally, i.e,
template <class T>
Array<T>::Array(const Array &other) : size(other.size), arr(new T[size])
{ // ^^^^^^
for (int i = 0; i < size; ++i)
arr[i] = other.arr[i];
} // ^^^^^
now apply it to this situation.
Also,
template <class T>
void selectionSort(Array<T> &a) {
// I'm not sure I understand what this is supposed to do that's different from the above selectionSort.
// I know that & is the reference operator, so should I just return whatever &a is?
}
You won't be returning anything here considering void as the return and the use of the reference. You pass by reference as opposed to by value so that what you do in the function is persistent. You could choose to pass back the sorted array and not use a reference but I'm fairly certain it'd be slower overall considering the assignment and copy. That's why the example from your other question is using const Array &other. It prevents the entire array, which may be large, from being copied and sent to the function as well as being changed.

operator overload for dynamic array giving strange error

I'm getting an error regarding "disgarded qualifiers" when I use this. The Entier class is posted below.
cout << d // where d is of type dynamic_array.
The global overloaded function:
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
A public member of dynamic_array
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
Entire Class dynamic array:
/*
Needs a reszie function added
Merge sort is better for sequential, stable(equal elements not re-arranged, or
*/
#include "c_arclib.cpp"
using namespace std;
template <class T> class dynamic_array
{
private:
T* array;
T* scratch;
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];
}
}
}
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);
}
public:
int size;
dynamic_array(int sizein)
{
size=sizein;
array = new T[size]();
}
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
int merge_sort()
{
scratch = new T[size]();
if(scratch != NULL)
{
merge_recurse(0, size);
return 1;
}
else
{
return 0;
}
}
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();
}
}
void order_to_array()
{
int* k;
int i = 0;
for (k = array; k != array + size; ++k)
{
*k=i;
++i;
}
}
void rorder_to_array()
{
int* k;
int i = size;
for (k = array; k != array + size; ++k)
{
*k=i;
--i;
}
}
};
template <class T> std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
{
data.print_array(stream);
return stream;
}
int main()
{
dynamic_array<int> d1(1000000);
d1.order_to_array();
clock_t time_start=clock();
d1.merge_sort();
clock_t time_end=clock();
double result = (double)(time_end - time_start) / CLOCKS_PER_SEC;
cout << result;
cout << d1;
}
The problem is in following lines:
template <class T>
std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data)
^^^^^^
and
void print_array(std::ostream &os = cout) /* const */
^^^^^ missing
Since you are passing data as const& to operator <<, you have to maintain its const qualification. i.e. data cannot call any non-const member of class dynamic_array. You can solve this problem in 2 ways:
pass data as simple dynamic_array<T>& to operator <<
make print_array a const method (uncomment above)
"Discards const qualifiers", presumably...
Replace:
void print_array(std::ostream &os = cout)
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
void print_array()
{
for (int i = 0; i < size; i++) cout << array[i] << endl;
}
...with...
void print_array(std::ostream &os = cout) const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
...or, better still ...
void print_array(std::ostream &os = cout) const
{
std::copy(array, array + size, std::ostream_iterator<T>(os, "\n"));
}
This member function can be declared const since it doesn't modify any attributes of the class. See the FAQ on Const-Correctness.
Your second print_array() method is redundant since the first takes a default argument of std::cout.