When I run it with the data type integer, it works perfectly fine but when I run it with string, it does not work.
Container storage capacity = 2. Currently, container contains 2 elements. The contents of the container: aaa bbb
after this output, it does not go further.
I do not know if the problem is about allocate function.
[Done] exited with code=3221226356 in 0.518 seconds This is the error I got
people are saying that this error is heap corruption. but I do not even know what that means and how to fix it. I just started to learn coding. I am sorry for my ignorance.
#include <iostream>
#include <String>
using namespace std;
template <class T>
class container
{
template <class S>
friend ostream& operator<<(ostream& out, container<S> &cobj);
// Postcondition: contents of the container object cobj is displayed
public:
container();
// Postcondition: an empty container object is created with data members arr set to NULL, n set to -1 and Capacity set to 0
container(container<T> &cobj);
// copy constructor; required as one of the Big-3 (Big-5) because of the presence of a pointer data member
// Postcondition: a new container object is created as a "deep" copy of cobj. (the default version creates a “shallow” copy!)
container(T* start, T* end);
// 3rd constructor; maps or copies the contents of a T-type array from a[start]...a[end] to the newly created container object.
// Note: 'end' is the address of the imaginary element to the immediate right of the last array element
// Postcondition: the arr array of the newly created container object has been initialized with the contents of T-type array
~container();
// Destructor; required as one of the Big-3 (or Big(5) because of the presence of a pointer data member. Default version results in
// memory leak!
// Postcondition: dynamic memory pointed to by arr has been release back to the “heap” and arr set to NULL or nullptr
// In order to see the action, message "destructor called and dynamic memory released!" is displayed
container operator=(container<T> &cobj2);
// overloaded assignment operator. The default version cannot be used because it results in a shallow copy!
// Postcondition: cobj2 is assigned to the calling object
bool isEmpty();
// Postcondition: returns true is nothing is stored; returns false otherwise
bool isFull();
// Postcondition: returns true if arr array is filled to capacity; returns false otherwise
int size();
// Postcondition: returns the size or the number of elements (values) currently stored in the container
int capacity();
// Postcondition: returns the current storage capacity of the container
void insertBack(T &newVal);
// Postcondition: if container is not full, newVal is inserted at the end of the array;
// otherwise, double the current capacity followed by the insertion
bool deleteBack();
// Precondition: The array must not be empty
// Postcondition: the last element stored in the array is removed! size of the container is decremented by 1, capacity unchanged
void insertFront(T &newVal);
// Postcondition: returns true if the container is not full and newVal is inserted at the front of the array;
// otherwise, double the current storage capacity followed by the insertion
bool deleteFront();
// Postcondition: front element of arr is deleted, all other elements in arr are left-shifted by one position;
// size of arr is decremented by 1, capacity remains unchanged.
void insertSorted(T newVal);
// Postcondition: newVal is inserted in arr of the container object in such a way that the resulting arr array remains sorted
void clear();
// Postcondition: all elements in arr of calling container object are cleared and the dynamic memory is released back to “heap”
int linearSearch(T target);
// Linear search the arr array for the existence of the target value
// Postcondition: if target value is found, returns sub of arr[sub] in which the target value is stored; otherwise returns -1
int binarySearch(T target);
// Precondition: the array arr must be sorted (ascending order is assumed)
// Postcondition: if target is found, returns value of the sub in arr[sub] where the target value is stored; otherwise returns -1
void sort();
// Use a sort algorithm you have not used before (e.g., selection sort, insertion sort, etc. assuming you had used bubble sort already.
// Postcondition: the array arr of the container class in ascending order
bool insertPos(int sub, T newVal);
// Precondition: 1) 0 <= sub <= n; i.e., it must be within the range of the arr array.
// Postcondition: If sub is in range, newVal is inserted in arr[sub]; affected elements from arr[sub] ... arr[n] are right- shifted one step
private:
void shiftRight();
// shift arr[n] ... arr[0] to arr[n+1]...arr[1] to make arr[0] available to store the inserted value
// Postcondition: all elements from arr[0] to arr[n] are shift one position to the right
void shiftLeft();
// shift arr[1] ... arr[n] to a arr[0]...arr[n-1]
// Precondition: the container must not be empty
// Postcondition: all element from arr[1] to arr[n-1] are shifted one position to the left
void allocate(T* &temp);
// Postcondition: if Capacity = 0, allocate a single location; otherwise the current capacity is doubled
T *arr;
int Capacity; // Note: Capital 'C' as capacity is used as a function name
int n; // size or actual # of values currently stored in the container; n <= SIZE
};
template <class T>
ostream& operator<<(ostream& out, container<T> &cobj)
{
out << "Container storage capacity = " << cobj.Capacity << endl;
out << "Currently, container contains " << cobj.size() << " elements." << endl;
out << "The contents of the container:" << endl;
if(cobj.size() == 0)
out << "***Container is empty!!" << endl;
else{
for(int i = 0; i <= cobj.n; i++){
out << cobj.arr[i] << " ";
}
out << endl;
}
return out;
}
template <class T>
container<T>::container()
{
arr = nullptr;
n = -1;
Capacity = 0;
}
template <class T>
container<T>::~container()
{
clear();
cout << "Destructor called and dynamic memory released!" << endl;
}
template <class T>
bool container<T>::isEmpty()
{
return (n == -1);
}
template <class T>
bool container<T>::isFull()
{
return (n == Capacity-1);
}
template <class T>
int container<T>::size()
{
return n+1;
}
template <class T>
int container<T>::capacity()
{
return Capacity;
}
template <class T>
void container<T>::insertBack(T &newval1)
{
allocate(arr);
n++;
arr[n] = newval1;
}
template <class T>
bool container<T>::deleteBack()
{
if(isEmpty())
return false;
else{
n--;
return true;
}
}
template <class T>
void container<T>::insertFront(T &newval)
{
allocate(arr);
for(int i = n; i > -1; i--){
arr[i+1] = arr[i];
}
n++;
arr[0] = newval;
}
template <class T>
bool container<T>::deleteFront()
{
if(isEmpty())
return false;
else{
for(int i = 1; i <= n; i++){
arr[i-1] = arr[i];
}
n--;
return true;
}
}
template <class T>
void container<T>::clear()
{
delete arr;
arr = nullptr;
Capacity = 0;
n = -1;
}
template <class T>
void container<T>::allocate(T* &temp)
{
if(Capacity == 0){
temp = new T;
Capacity = 1;
}else{
Capacity *= 2;
T *tmp = new T[Capacity];
for(int i = 0; i <= n; i++)
{
tmp[i] = temp[i];
}
delete temp;
temp = tmp;
}
}
int main()
{
container<string> obj;
cout << obj << endl << endl;
string array[] = {"aaa", "bbb", "ccc"};
cout << "Currently, the container object contains " << obj.size() << " elements or values" << endl << endl;
cout << "Now we insert 3 values at the back of the array, one at a time:" << endl;
for(int i = 0; i < 3; i++){
obj.insertBack(array[i]);
cout << obj << endl;
}
cout << "Now we delete all 3 values from the back of the array, one at a time:" << endl << endl;
bool res;
for(int i = 0; i < 3; i++){
res = obj.deleteBack();
if(!res){
cout << "We cannot delete from an empty array" << endl;
break;
}else
cout << obj << endl;
}
cout << "Now we try to delete from an empty container: "<< endl << endl;
res = obj.deleteBack();
if(!res)
cout << "We cannot delete from an empty array" << endl << endl;
else
cout << obj << endl;
/*cout << "Now we insert 3 values at the front of the array, one at a time:" << endl << endl;
for(int i = 0; i < 3; i++){
obj.insertFront(array[i]);
cout << obj << endl;
}
cout << "Now we delete all 3 values from the back of the array, one at a time:" << endl << endl;
for(int i = 0; i < 3; i++){
res = obj.deleteFront();
if(!res){
cout << "We cannot delete from an empty array" << endl;
break;
}else
cout << obj << endl;
}*/
return 0;
}