C++ Array Based Stack - c++

I am trying to double a stack once it gets full. I have tried calling the copy constructor, and when I call it the stack doesn't keep pushing words.
The code run perfectly before it gets full, but once it gets full is where my problem occur. What am I doing wrong?
#include<iostream>
#include<fstream>
#include<string>
//#include "ArgumentManager.h"
#include "Stack.h"
using namespace std;
int main(int argc, char** argv){
//ArgumentManager am(argc, argv); //Instantiating parser for command line arguments
//ReAdInG tHe InPuT fIlE nAmE
//ifstream infile(am.get("A").c_str()); // file to read from, getting name from command line
//ofstream outfile(am.get("C").c_str()); // output file, getting name from command line
ifstream infile;
ofstream outfile;
arrayStack<string> firstStack(10);
arrayStack<string> secondStack(firstStack);
firstStack.stackInitialize();
infile.open("input.txt");
outfile.open("output.txt");
//iF tHe FiLe IsNt ReAd
if(!infile){
std::cout << "ErRor[Input file not Found] YoU hAd OnE jOb....ShAmE" << endl;
std::cout << "ExItInG PrOgRaM!!! GoOdByE" << endl;
return 0;
};
string tester; // to get the words
//READ FROM INFILE AND OUTPUT TO OUTFILE
while(infile >> tester){
for(int i = 0; i < tester.size(); ++i)
{ // CHECK IF A SPECIAL CHARACTER IS ON THE FILE
if(!((tester[i] >= 'a' && tester[i] <= 'z')||(tester[i] >= 'A' && tester[i]<= 'Z')))
{
tester[i] = '\0';
}
}
firstStack.push(tester);
};
while(!firstStack.stackIsEmpty())
{
string b = firstStack.top();
outfile << b << " ";
cout << b << " ";
if(firstStack.stackIsFull()){
secondStack.push(tester)
};
firstStack.pop();
}
infile.close();
outfile.close();
return 0;
}
Also I have tried to call the copy constructor in the push function such as:
template <class Type>
void arrayStack<Type>::push(const Type& word){
if(topStack != maxStackSize){
list[topStack] = word; // adding a new word to the STACK
topStack++;
}
else
cout << "YOU KNOW YOU CAN'T ADD TO A FULL STACK............SHAME" << endl;
arrayStack<Type> newArrayStack(maxStackSize*2);
for(int i = 0; i < maxStackSize; i++){
newArrayStack.push(list[i]);
}
newArrayStack.push(word);
stackCopy(newArrayStack);
}
It doesn't work either.
Below is the Stack Template
//ARRAY BASED STACK TEMPLATE
#ifndef H_ArrayStack
#define H_ArrayStack
#include <iostream>
using namespace std;
template <class Type>
class arrayStack{
private:
int maxStackSize; // the maximum height of the STACK
int topStack; // the top of the STACK
void stackCopy(const arrayStack<Type>& newArrayStack);
Type *list; // array based needs pointer to hold the stack element
public:
const arrayStack<Type>& operator=(const arrayStack<Type>&);
void stackInitialize(){ topStack = 0;}; //Ensure the array stack is empty
bool stackIsEmpty() const{return(topStack == 0);}; //check if stack is empty, is const so will not be messed with
bool stackIsFull() const{return topStack == maxStackSize;}; // just like line 8 except check if it is full
void push(const Type& word); // add a word to the array STACK
void pop(); //remove a word from the array and increment the top
Type top() const; //returns the top of the STACK
arrayStack(int size); //the default constructor
arrayStack(const arrayStack<Type>& newArrayStack); // the copy constructor which allows a new STACK
~arrayStack(){delete [] list;}; // it is an array so to ensure no memory leaks the stack must be deleted after use
};
template <class Type>
void arrayStack<Type>::push(const Type& word){
if(topStack != maxStackSize){
list[topStack] = word; // adding a new word to the STACK
topStack++;
}
else{
cout << "YOU KNOW YOU CAN'T ADD TO A FULL STACK............SHAME" << endl;
int size = maxStackSize;
maxStackSize *= 2;
Type *temp = new Type[maxStackSize]; // create temp and double the size of list
for(int i = 0; i < size; i++){ // copy over all the values
temp[i] = list[i];
}
delete [] list; // delete the list
list = temp; // point to the resized list
list[topStack] = word;
topStack++;
}
}
template <class Type>
void arrayStack<Type>::pop(){
if (!stackIsEmpty()){
topStack--;
}
}
template <class Type>
Type arrayStack<Type>::top() const{
if(topStack == 0){
return 0;
}
else
return list[topStack - 1];
}
template <class Type>
arrayStack<Type>::arrayStack(int size){
maxStackSize = size;
topStack = 0;
list = new Type[maxStackSize];
}
template <class Type>
void arrayStack<Type>::stackCopy(const arrayStack<Type>& newArrayStack){
maxStackSize = newArrayStack.maxStackSize;
topStack = newArrayStack.topStack;
list = new Type[maxStackSize];
for(int j = 0; j < topStack; j++)
list[j] = newArrayStack.list[j];
}
template <class Type>
arrayStack<Type>::arrayStack(const arrayStack<Type>& newArrayStack){
stackCopy(newArrayStack);
}
template <class Type>
const arrayStack<Type>& arrayStack<Type>::operator=(const arrayStack<Type>& newArrayStack){
if(this != &newArrayStack)
stackCopy(newArrayStack);
return *this;
}
#endif

From:
arrayStack<Type> newArrayStack(maxStackSize*2);
for(int i = 0; i < maxStackSize; i++){
newArrayStack.push(list[i]);
}
newArrayStack.push(word);
stackCopy(newArrayStack);
To:
int size = maxStackSize;
maxStackSize *= 2;
Type *temp = new Type[maxStackSize]; // create temp and double the size of list
for(int i = 0; i < size; i++){ // copy over all the values
temp[i] = list[i];
}
delete [] list; // delete the list
list = temp; // point to the resized list
list[topStack] = word;
topStackk++;
Try this in you push function this will double the size of the stack. Like someone mentioned in the comments you have errors in your copy constructor and stackcopy function

Related

Values in dynamic array cannot be assigned

I am using a stack to reverse a given string. Each character of the string is pushed onto the stack, then they are popped back into a new string which is returned to main. But for some reason, the value of stack[top] in the stack class code never seems to change.
#include <iostream>
#include <string>
using namespace std;
const int size = 4;
class Stack{
private:
//char stack[size];
char* stack;
int top;
public:
Stack()
{
top = -1;
}
void Init_Size(int size)
{
stack = new char[size];
}
bool isFull()
{
if (top == (size - 1))
return true;
return false;
}
bool isEmpty()
{
if (top == -1)
return true;
return false;
}
void push(char c)
{
if (isFull())
{
cout << "STACK IS FULL" << endl;
return;
}
top++;
stack[top] == c;
cout << "PUSHED" << stack[top] << " ONTO STACK" << endl;
}
char pop()
{
if (isEmpty())
{
cout << "STACK IS EMPTY" << endl;
return '/'; //error
}
char temp = stack[top];
cout << stack[top] << endl;
top--;
cout << "POPPED" << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}
I tried using a normal array for the stack instead of a dynamic one, but no change, however, I did notice that the value of the stack array can be changed but only in the void Init_Size(int size) function and I'm not sure why.
I see a number of errors in your program:
size: You have a global constant size set to 4 which is used in your isFull function, independent of the local size parameter used in Init_Size. Make this a class variable instead.
Your push function has the line stack[top] == c with two = instead of one - thus comparing the value against stack instead of setting stack. Turn on warnings and you should have found this yourself
ReverseString assigns directly to result[i] without ever setting the size of result. You could have used the str variable instead, since that is just a copy.
Those three are the major errors that need fixing for your program to work, but there are several minor issues as well, like using namespace std; thereby making size ambigious, making unnecessary copies of strings, using new and c-style arrays etc.
You have a problem with creation and deletion of your arrays here in your program as well as a few small misshaps on the way.
Fix:
#include <iostream>
#include <string>
using namespace std;
class Stack{
private:
//char stack[size];
int size;
char* stack;
public:
Stack() : size(0), stack(NULL) {}
~Stack() {if (stack != NULL) delete stack;} //THIS IS NEEDED HERE
void Init_Size(int newSize)
{
if (stack != NULL) delete stack;
size = newSize;
stack = new char[newSize]; //CREATES DYNAMIC ARRAY WHICH YOU NEED TO REMEMBER TO REMOVE OTHERWISE MEMORY LEAK
}
void push(char c) //adds
{
//adding here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL) Init_Size(1);
char* newArray = new char[size+1];
for(int i = 0; i < size; i++)
{
newArray[i] = stack[i];
}
newArray[size] = c;
delete stack;
stack = newArray;
size++;
cout << "PUSHED " << stack[size-1] << " ONTO STACK" << endl;
}
char pop()
{
//removing here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL)
{
cout << "Stack empty" << endl;
return '\0';
}
char* newArray = new char[size-1];
for(int i = 0; i < size-1; i++)
{
newArray[i] = stack[i];
}
char temp = stack[size-1];
delete stack;
stack = newArray;
size--;
cout << "POPPED " << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}

C++ how to implement a resizable stack array?

In one of my earlier lab exercises I implemented a simple stack program
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int count = 0; //stores the indexed number
string myStack[20]; //stores the data from file
string fileName;
fstream readFile;
string storeFile; //stores the data as a string
//function declarations/prototypes
void push(string aString);
string top();
string pop();
bool isEmpty();
int main(int argc, char *argv[])
{
fileName = "file.txt";
readFile.open(fileName); //attempts to read the file
while(readFile >> storeFile){
if(readFile.bad()) {
cerr << "File failed to read " << endl;
break; //loop terminates
} else {
push(storeFile); //pushes file to stack
}
}
readFile.close();
while(isEmpty() !=true) { //while file is not emptpy return the top stack.
cout << top() << endl;
pop();
}
return 0;
}
void push(string value) {
myStack[count] = value;
count++;
}
string pop() {
if(count < 0) {
return NULL;
} else {
count--; //decrement count for stack
return myStack[count]; //return top value
}
}
string top() { //returns the current element at the top of the stack
return myStack[count];
}
bool isEmpty() { //checks whether or not the stack is empty
if(count < 0) {
return true;
}
else return false;
}
I am now required to revisit this program, however, this time modify it so that If you attempt to push data onto a full stack you should create a new array of twice the current size, copy the data from the old stack to the new stack and then delete the old stack without using STL or classes. We are allowed to use dynamic memory
So if the input, for example, looked something like this with an array size of 2
push 1
push 1
push 1
push 1
push 1
pop
pop
push 1
Then the output would look like this
Stack doubled from 2 to 4.
Stack doubled from 4 to 8.
Stack contains 4 entries.
How would I implement this? Thankyou
Push attempt
int dataCount = 0;
const int SIZE = 5;
int capacity = 0;
int myStack[SIZE];
void push(int value)
{
if(SIZE == capacity) {
cout << "Doubling current size " << endl;
capacity = capacity * 2;
int* temp = new int[capacity];
copy_n(myStack, SIZE, temp);
std::swap(myStack, temp);
delete[] temp;
}
myStack[dataCount] = value;
dataCount++;
}
What you are asking for requires the stack array to be allocated in dynamic memory, eg:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int count = 0; //stores the indexed number
int capacity = 0; //stores the allocated size
string *myStack = NULL; //stores the data from file
//function declarations/prototypes
void push(const string &aString);
string top();
void pop();
bool isEmpty();
void cleanup();
int main(int argc, char *argv[])
{
string storeFile; //stores the data as a string
string fileName = "file.txt";
ifstream readFile(fileName); //attempts to read the file
while (readFile >> storeFile) {
push(storeFile); //pushes file to stack
}
if (readFile.bad()) {
cerr << "File failed to read " << endl;
}
readFile.close();
while (!isEmpty()) { //while file is not empty return the top stack.
cout << top() << endl;
pop();
}
cleanup();
return 0;
}
void push(const string &value) {
if (count == capacity) {
int newCapacity = (capacity == 0) ? 20 : (capacity * 2);
string *newStack = new string[newCapacity];
for(int i = 0; i < count; ++i) {
newStack[i] = myStack[i];
}
delete[] myStack;
myStack = newStack;
capacity = newCapacity;
}
myStack[count] = value;
++count;
}
string top() {
if (count <= 0) {
return string();
}
return myStack[count-1]; //return top value
}
void pop() {
if (count > 0) {
--count; //decrement count for stack
myStack[count] = "";
}
}
bool isEmpty() {
return (count < 1);
}
void cleanup() {
capacity = count = 0;
delete[] myStack;
myStack = NULL;
}
Create a class That has
-Array start pointer
-current size
-the current position of the stack pointer
a method that inflate the array , delete the previous one and copy the data of the previous
-have a method that push on the stack and one that pops on top of the stack
You can event handle shrinking the stack when pop is less than length of the stack /2

I have a weird segmentation fault, std::length_error and sometimes my code works?

I finished some code that prints out how many times a word shows up. However, when I finished and tried to run the code on a different compiler it did not work. Firstly, here is a picture of my code working on my initial file:
But when I used a different compiler (onlinegdb) I get this error:
The thing that confused me the most is; when I try and replicate the file into a new VS Code .cpp file, it does not work. It runs the code but then prints out nothing. When I went into gdb I find this error:
If anyone knows where the segmentation fault/std::length_error are happening at please let me know, and if you have any recommendations that would be great! Also, knowing why I get different results on the same compiler (VS Code) would also be helpful. Here is my code:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
class WordOccurrence
{
public:
WordOccurrence(const string& word="", int num=1)
{
word_ = word;
num_ = num;
}
bool matchWord(const string & compare)
{
if(word_ == compare)
return true;
else
return false;
}
void increment()
{
num_++;
}
string getWord() const
{
return word_;
}
int getNum() const
{
return num_;
}
private:
string word_;
int num_;
};
class WordList
{
public:
friend bool equal(const WordList&, const WordList&);
WordList();
WordList(const WordList &);
~WordList();
WordList operator= (const WordList &);
void addWordFile(WordList w);
void addWord(const string &);
void print();
private:
WordOccurrence *wordArray_;
int size_;
};
WordList::WordList()
{
size_ = 0;
wordArray_ = new WordOccurrence [size_];
}
WordList::WordList (const WordList &neww)
{
size_ = neww.size_;
wordArray_ = new WordOccurrence[size_];
for (int i = 0; i <= (size_ - 1); i++)
wordArray_[i] = neww.wordArray_[i];
}
WordList::~WordList ()
{
delete [] wordArray_;
}
WordList WordList::operator= (WordList const &overload)
{
WordList temp(overload);
swap(wordArray_, temp.wordArray_);
swap(size_, temp.size_);
return *this;
}
void WordList::addWord(const string& word)
{
if(size_ == 0)
{
WordOccurrence *first_array = new WordOccurrence[1];
first_array[0] = word;
delete[] wordArray_;
wordArray_ = first_array;
delete[] first_array;
size_++;
return;
}
//if the word is already in the array, we increase the count of it by 1
for (int i = 0; i < size_; i++)
{
if (wordArray_[i].matchWord(word))
{
wordArray_[i].increment();
return;
}
}
//if it is not in the array already, we need to increase its size and then add the new word to the wordarray.
WordOccurrence *new_array = new WordOccurrence[size_+1];
for (int i = 0; i < size_; i++)
{
new_array[i] = wordArray_[i];
}
new_array[size_] = WordOccurrence(word);
delete[] wordArray_;
size_++;
wordArray_ = new_array;
delete[] new_array;
}
void WordList::print()
{
//to output to a file because when we get a lot of words it's kinda hard to see on just the terminal
ofstream myfile ("output.txt");
WordList sortedList(*this);
//Sorting from smallest to largest
int smallest = wordArray_[0].getNum();
for (int i = 1; i < size_; i++)
{
//stores the smallest value into smallest
if(wordArray_[i].getNum() < smallest)
smallest = wordArray_[i].getNum();
}
int location = 0;
//stores values from start to finish in the new list starting at location sortedList[0]
while(location < size_)
{
for(int i = 0; i < size_; i++)
{
//runs through the new list until it finds a value that is apart of the smallest/rarest words
if(wordArray_[i].getNum() == smallest)
{
sortedList.wordArray_[location] = wordArray_[i];
location++;
}
}
//increases the value of smallest allowing for numbers with greater found values to be sorted
smallest++;
}
//prints out the sorted version of wordarray
for(int i = 0; i < size_; i++)
{
string word = sortedList.wordArray_[i].getWord();
int count = sortedList.wordArray_[i].getNum();
cout << "Word: " << word << " Amount: " << count << endl;
//for longer amounts of text, it was hard to see on a editor so I also have it out to a file.
myfile << "Word: " << word << " Amount: " << count << endl;
}
}
int main()
{
WordList w;
w.addWord("one");
w.addWord("one");
w.addWord("two");
w.addWord("three");
w.addWord("four");
w.addWord("four");
w.addWord("four");
w.addWord("four");
w.addWord("five");
w.addWord("five");
w.addWord("five");
cout << "Sorted list" << endl;
w.print();
}
This is bugged
WordOccurrence *first_array = new WordOccurrence[1];
first_array[0] = word;
delete[] wordArray_;
wordArray_ = first_array;
delete[] first_array;
size_++;
return;
You assign first_array to wordArray_ and then you delete it. This leaves wordArray_ as an invalid pointer. Just remove delete[] first_array;. Two deletes and only one new should have been a clue that something was wrong.
Same bug later on in the same function
WordOccurrence *new_array = new WordOccurrence[size_+1];
for (int i = 0; i < size_; i++)
{
new_array[i] = wordArray_[i];
}
new_array[size_] = WordOccurrence(word);
delete[] wordArray_;
size_++;
wordArray_ = new_array;
delete[] new_array;
delete[] new_array; should not be there.

Array resize function in dynamic memory

I'm making a function to resize an array in dynamic memory and it's not working..
here's the code:
template <class Type>
void Array<Type>::Resize(int newSize)
{
if(newSize==size)
return;
if(newSize<=0)
return;
Type *temp = new Type[newSize];
int min=(newSize>size)?size:newSize;
for(int i=0; i<min; i++)
temp[i]=elements[i];
delete []elements;
elements = temp;
temp = NULL;
}
the problem is in these two statements
delete []elements;
elements = temp;
cause when i comment them the program works properly,
but it actually doesn't do what is supposed to do..
I think the problem is something that is being destroyed when getting out of the function scope and I have to call it by reference but I can't actually cause this is a member function.
Here's the whole header file:
#include<string>
#include<iostream>
using namespace std;
#ifndef ARRAY_H
#define ARRAY_H
template <class Type>
class Array
{
public:
Array (int s);
Array (const Array& obj);
~Array ();
const Array& operator= (const Array& obj);
Type GetElement (int index) const;
void SetElement (Type ele, int index);
void Resize (int newSize);
void Print () const;
void Destroy ();
private:
int size;
Type* elements;
};
template <class Type>
Array<Type>::Array(int s)
{
if(s<0)
return;
size=s;
elements = new Type[size];
}
template <class Type>
Array<Type>::Array(const Array &obj)
{
size = obj.size;
elements = new Type[size];
for(int i=0; i<size; ++i)
elements[i]=obj.elements[i];
}
template <class Type>
Array<Type>::~Array()
{
delete [] elements;
elements = NULL;
size = 0;
}
template <class Type>
void Array<Type>::Destroy()
{
delete [] elements;
elements = NULL;
size = 0;
}
template <class Type>
const Array<Type> &Array<Type>::operator=(const Array &obj)
{
if(this != &obj)
{
size = obj.size;
if(elements != NULL)
delete [] elements;
elements = new Type[size];
for(int i=0; i<size; i++)
elements[i] = obj.elements[i];
}
return *this;
}
template <class Type>
Type Array<Type>::GetElement(int index) const
{
if(index<0 || index>=size)
cout << "Sorry, this operation can not be proceeded \n";
else
return elements[index];
}
template <class Type>
void Array<Type>::SetElement(Type ele, int index)
{
if(index<0 || index>=size){
cout << "Sorry, this operation can not be proceeded \n";
return; }
else
elements[index] = ele;
}
template <class Type>
void Array<Type>::Print() const
{
for(int i=0;i<size; ++i)
cout << elements[i] << endl;
}
template <class Type>
void Array<Type>::Resize(int newSize)
{
if(newSize==size)
return;
if(newSize<=0)
return;
Type *temp = new Type[newSize];
int min=(newSize>size)?size:newSize;
for(int i=0; i<min; i++)
temp[i]=elements[i];
delete []elements;
elements = temp;
temp = NULL;
}
#endif
You forgot to do one thing in the Resize() function, and that is to update the member size with the new size after reallocation. This will cause it to access memory beyond the end of the buffer after a resize with a smaller new dimension, e.g.:
Array<int> arr(10);
// set the 10 values
arr.Resize(5);
// here the buffer will have 5 elements, but arr.size is still 10
arr.Print(); // this will read elements 0 - 9, not 0 - 4
Couple of observations
if(newSize==size)
size does not exist
delete []elements;
elements = temp;
You are attempting to copy to an array you have just deleted, which was never created in the first place.
What is meant by "does not work" and "the program works properly,"?

Expanding/shrinking a dynamic array

I have an assignment to create a template container class with a dynamic array that can be increased and decreased. When the array is displayed, I get either garbage numbers or no numbers at all for the elements in the array where it was expanded(so if it expanded on the fifth element, the value would turn to junk after I enter the sixth). When I try to remove elements I get a Debug Assertion Failed error.
Here is my code:
template <class T> class container {
public:
container(); // constructor
// Post-condition: count is set to -1 and dynamic array size set to 5
~container(); //destructor
void insert(T &n);
// Pre-condition: a value is passed to the function
// Post-condition: if data array is not full, increment count by 1 and insert the value in the array
// Otherwise, display "Container full! No insertion is made."
void remove();
//Post-condition: if data array is not empty, remove the data[count] element in data array and decrement count by 1;
//otherwise, display a message "Container empty! Nothing is removed from it."
void display();
// Post-condition: if the array is not empty, displays all values in data array similar to the sample output;
//Otherwise, display the message “Container is now empty!"
void fillarray(container c);
//pre-condition: a container c is passed to the function
//post-condition: dynamic array of chosen type is created and filled continuously with user entered values
private:
bool empty;
//Post-condition: returns true is the array is empty, otherwise returns false
T *data; // dynamically allocated array used to store or contain the inserted values
int count; // indicates how many values have been inserted
int max;
};
template <class T> container<T>::container()
{
count = -1;
max = 5;
data = new T[max];
assert(data != NULL);
}
template <class T> container<T>::~container()
{
delete [] data;
}
template <class T> void container<T>::insert(T &n)
{
if (count >= (max - 1))
{
max = max * 2;
cout << "\nContainer full! Array size is increased by " << max/2 << ".";
T *temp = new T[max];
assert(temp != NULL);
for (int i = 0; i < count; i++)
temp[i] = data[i];
delete [] data;
data = temp;
count++;
data[count] = n;
}
else
count++;
data[count] = n;
}
template <class T> void container<T>::remove()
{
empty = count < 0;
if (empty == 1)
{
cout << "\nContainer empty! Nothing is removed from it.";}
else
{
count--;
T *temp1 = new T[max];
assert(temp1 != NULL);
for (int i = 0; i < count; i++)
temp1[i] = data[i];
delete [] data;
data = temp1;
}
}
template <class T> void container<T>::display()
{
empty = count < 0;
if (empty == 1)
{
cout << "\nContainer is now empty!";}
else
{
for (int i = 0; i <= count; ++i)
cout << " " << data[i];
}
}
template <class T> void container<T>::fillarray(container c)
{
char ans;
do
{
T value;
cout << "\nEnter a value:";
cin >> value;
c.insert(value);
cout << "\nAfter inserting, the \"container\" contains:" << endl;
c.display();
cout << "\nEnter more? (Y/y or N/n)";
cin >> ans;
} while (ans == 'Y' || ans == 'y');
for (int i = 0; i <= count; i++)
{
c.remove();
cout << "\nAfter removing a value from it, the \"container\" contains:" << endl;
c.display();
cout << endl;
}
}
// The main driver function to be used to test implementation
int main()
{
char choice;
cout << "\nEnter S for string container, D for double";
cin >> choice;
if (choice == 'S' || choice == 's')
{
container<string> c;
c.display();
c.fillarray(c);
}
else if(choice == 'D' || choice == 'd')
{
container<double> c;
c.display();
c.fillarray(c);
}
return 0;
}
template <class T> void container<T>::fillarray(container c)
{
//...
}
This function actually involves two container<T> objects: *this and c.
Since you "pass by value" (the function parameter is not a reference), c in fillarray is created as a copy of the original c in main. In fillarray you modify c, which deletes and changes c.data, but this->data still contains the dangling pointer to the original storage. Before long, you get undefined behavior; luckily enough bad things happened you could tell something was wrong.
Per the Rule of Three (Plus Two), if a class has a destructor, you probably should not allow the compiler to generate the default copy constructor and copy assignment, and you may want to consider implementing a move constructor and move assignment.
The easiest, and sometimes best, way of meeting that rule is to disable copying:
template <class T> class container
{
public:
container(container const&) = delete;
container& operator=(container const&) = delete;
//...
};
Then the compiler will make sure you don't accidentally make a copy and get yourself into this sort of trouble.
You make life confusing by count referring to maximum index rather than the number of entries. Using your scheme though, this line in insert is odd:
for (int i = 0; i < count; i++)
As that won't copy the final entry.