Segmentation Fault when Overloading addition operator and dynamic vectors - c++

I'm trying to overload the addition operator but I keep getting a segmentation fault even though I'm passing in the argument by value after it's memory has been deallocated. Anybody have any idea what I could be doing wrong. Also once I get this running properly after fixing the overloaded addition, I need to use vectors instead of pointing to arrays which I have no idea how to declare in a manner equivalent to what I've wrritten for arrays.
RowAray.h
#ifndef ROWARAY_H // if constant ROWARAY_H not defined do not execute
#define ROWARAY_H // defines constant ROWARAY_H
#include <new> // Needed for bad_alloc exception
#include <cstdlib> // Needed for the exit function
template <class T>
class RowAray{
private:
int size;
T *rowData;
void memError(); // Handles memory allocation errors
void subError(); // Handles subscripts out of range
public:
RowAray(T); //used to construct row Array object
~RowAray(){delete [] rowData;} //used to deallocate dynamically allocated memory from Row array
int getSize(){return size;} //inline accessor member function used to return length of Row array
void setData(int row, T value);
T getData(int i){return (( i >=0&& i < size)?rowData[i]:0);} //
T &operator[](const int &);
};
template <class T>
RowAray<T>::RowAray(T colSize){
size =colSize>1?colSize:1;
// Allocate memory for the array.
try
{
rowData = new T [size];
}
catch (bad_alloc)
{
memError();
}
// Initialize the array.
for (int count = 0; count < size; count++){
T value = rand()%90+10;
setData(count, value);
}
}
template <class T>
void RowAray<T>::memError()
{
cout << "ERROR:Cannot allocate memory.\n";
exit(EXIT_FAILURE);
}
template <class T>
void RowAray<T>::subError()
{
cout << "ERROR: Subscript out of range.\n";
exit(EXIT_FAILURE);
}
template <class T>
T &RowAray<T>::operator[](const int &sub)
{
if (sub < 0 || sub >= size)
subError();
else
return rowData[sub];
}
template <class T>
void RowAray<T>::setData(int row, T value){
//used to fill array with random 2 digit #s
*(rowData + row) = value;
}
#endif /* ROWARAY_H */
Table.h
#ifndef TABLE_H
#define TABLE_H
#include "RowAray.h"
template <class T>
class Table{
private:
int szRow;
int szCol;
RowAray<T> **records;
public:
Table(int,int); //used to construct Table object
Table(const Table &);
~Table(); //used to deallocate dynamically allocated memory from Table object
int getSzRow() const{return szRow;} //used to return row size
int getSzCol()const {return szCol;}
Table operator+(const Table &);
T getRec(int, int) const; //used to return inserted random numbers of 2d arrays
};
template <class T>
Table<T>::Table(int r, int c ){
//Set the row size
this->szRow = r;
//Declare the record array
records = new RowAray<T>*[this->szRow];
//Size each row
this->szCol = c;
//Create the record arrays
for(int i=0;i<this->szRow;i++){
records[i]=new RowAray<T>(this->szCol);
}
}
template <class T>
Table<T>::Table(const Table &Tab){
szRow=Tab.getSzRow();
szCol=Tab.getSzCol();
records = new RowAray<T>*[szCol];
for(int i = 0; i < this->szCol; i++){
records[i] = new RowAray<T>(szRow);
}
//set elements = to random value
for(int row = 0; row < szRow; row++){
for(int col = 0; col < this->szCol; col++){
int value = Tab.getRec(row, col);
records[col]->setData(row,value);
}
}
}
template <class T>
T Table<T>::getRec(int row, int col) const{
//if else statement used to return randomly generated numbers of array
if(row >= 0 && row < this->szRow && col >= 0 && col < this->szCol){
return records[row]->getData(row);
}else{
return 0;
}
}
template <class T>
Table<T>::~Table(){
//Delete each record
for(int i=0;i<this->szRow;i++){
delete records[i];
}
delete []records;
}
template <class T>
Table<T> Table<T>::operator+(const Table &Tab){
Table temp(Tab.getSzRow(), Tab.getSzCol());
//set elements = to random value for operation to
for(int row=0; row < szRow; row++){
for(int col=0; col < szCol; col++){
int value = getRec(row, col) + Tab.getRec(row, col);
temp.records[col]->setData(row,value);
}
}
return temp;
}
#endif /* TABLE_H */
main.cpp
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;
//User Libraries
#include "Table.h"
//Global Constants
//Function Prototype
template<class T>
void prntRow(T *,int);
template<class T>
void prntTab(const Table<T> &);
//Execution Begins Here!
int main(int argc, char** argv) {
//Initialize the random seed
srand(static_cast<unsigned int>(time(0)));
//Declare Variables
int rows=3,cols=4;
//Test out the Row with integers and floats
RowAray<int> a(3);
RowAray<float> b(4);
cout<<"Test the Integer Row "<<endl;
prntRow(&a,3);
cout<<"Test the Float Row "<<endl;
prntRow(&b,4);
//Test out the Table with a float
Table<float> tab1(rows,cols);
Table<float> tab2(tab1);
Table<float> tab3 = tab1 + tab2;
cout<<"Float Table 3 size is [row,col] = Table 1 + Table 2 ["
<<rows<<","<<cols<<"]";
prntTab(tab3);
//Exit Stage Right
return 0;
}
template<class T>
void prntRow(T *a,int perLine){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int i=0;i<a->getSize();i++){
cout<<a->getData(i)<<" ";
if(i%perLine==(perLine-1))cout<<endl;
}
cout<<endl;
}
template<class T>
void prntTab(const Table<T> &a){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int row=0;row<a.getSzRow();row++){
for(int col=0;col<a.getSzCol();col++){
cout<<setw(8)<<a.getRec(row,col);
}
cout<<endl;
}
cout<<endl;
}

You error stems from line 85 of Table.h, in you + operator overload:
temp.records[col]->setData(row,value);
should really be
temp.records[row]->setData(col,value);
Apart from that, I spotted another error in the same file in line 62 (method Table<T>::getRec(int row, int col)):
return records[row]->getData(row);
should be
return records[row]->getData(col);
Apart from those problems, I would highly advise you to rethink and restructure your code (maybe you could also try a code review), since a large part of it is superfluous in my opinion and some things could become problematic if you expand the project (for example, RowAray's constructor takes a T colSize as parameter where you should probably use an int or, better, a size_t. This code as it is will not work when T is not implicitly convertible to an integer type).

Related

How in C++ would you create a method that shuffles the the elements in a Generic Array

I am to make a Genetic Array class in C++ and in that class I am to give it a method called shuffle that shuffles(mixes up) the elements in that Array
I am using Repl.it to compile my code and this is the link:
https://repl.it/#jamy155/Exam1
In my code, I have 3 files. My main class, My genetic array class, and one other class.
In my array class, I have this method that is supposed to shuffle the array
//Array.h//
#include <bits/stdc++.h>
using namespace std;
template <typename T>
class Array {
Element<T>*data;
int size;
public:
// sets the size of the array
Array(int size){
this->data = new Element<T>[size];
this-> size = size;
}
int length(){
return this->size;
}
// add Element to the Array
void InsertAt(int i,T value){
data[i].set(value);
}
// prints all element in Array
void print(){
for(int i = 0 ; i<this->size; i++){
cout<<*data[i].get()<<" ";
}
void shuffler(Array arr[]){
int n = this->size;
// To obtain a time-based seed
unsigned seed = 50;
// Shuffling our array
shuffle(arr, arr+n,default_random_engine(seed)); // shuffle method
cout<<"\n";
for(int i=0;i<n;++i)
cout<<arr[i].get(i)<<" ";
}
};
This is my main class.
#include <iostream>
#include "Array.h"
using namespace std;
int main() {
cout << "Hello World!\n";
Array<int> *arr = new Array<int>(7);
arr->InsertAt(0,6);
arr->InsertAt(1,1);
arr->InsertAt(2,10);
arr->InsertAt(3,3);
arr->InsertAt(4,3);
arr->InsertAt(5,5);
arr->InsertAt(6,4);
arr->print();
arr->shuffler(arr); //error
It gives me an error "exited, segmentation fault".What am I doing wrong?

Segmentation fault: 11 in C++ IntVector

I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment

Declaring the templates in c++

// stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#include "Animal.h"
// TODO: reference additional headers your program requires here
class Animal
{
private:
int itsWeight;
public:
Animal(int);
Animal();
~Animal() {}
int getWeight() const { return itsWeight; }
void Display() const;
};
template <class T>
class Array
{
private:
T *pType;
int itsSize;
const int defaultSize = 10;
public:
//constructors
Array(int itsSize = defaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
//operators
Array& operator=(const Array&);
T& operator[](int offSet){ return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
//methods of Access
int getSize() const { return itsSize; }
};
//constructor
template <class T>
Array<T>::Array(int size) :
itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
{
pType[i] = 0;
}
}
//copy-constructor
template <class T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
}
//operator prisvoeniya
template <class T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
return *this;
}
//this is the file "Animal.cpp"
#include "stdafx.h"
#include "Animal.h"
Animal::Animal()
{
itsWeight = 0;
}
Animal::Animal(int weight)
{
itsWeight = weight;
}
void Animal::Display() const
{
cout << itsWeight;
}
// the main function
#include "stdafx.h"
int_tmain(int argc, _TCHAR* argv[])
{
Array<int> theArray; //Integer array
Array<Animal> theZoo; //Animal array
Animal *pAnimal;
//filling the array
for (int i = 0; i < theArray.getSize(); i++)
{
theArray[i] = i * 2;
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
for (int j = 0; j < theArray.getSize(); j++)
{
cout << "theArray[" << j << "]:\t";
cout << theArray[j]<<"\t\t";
cout << "theZoo[" << j << "]:\t";
theZoo[j].Display();
cout << endl;
}
return 0;
}
The problem is that: The compiler gives me the errors
Error 1 error C2648: 'Array<int>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Error 2 error C2648: 'Array<Animal>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Anybody can help me to understand that. I change the
const int defaultSize=10;
to
static const int defaultSize=10
then there is not errors but in that time show Debug Assertion Failed!
This part of your code is dodgy
{
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
The first line allocates an array of i*3 Animals, using their default constructor (which makes an Animal with itsWeight=0). In the second line you assign the first these newly allocated Animals to theZoo[i]. Finally, the third line tries to de-allocate the Animals.
The last line contains an error, since you call delete on a pointer obtained with new [].
The whole concept of creating objects on the heap only to immediately destroy them is quite dubious -- perhaps you come from another programming language, where this is the only way to create things? First, you could simply use an automatic variable
{
Animal a; // or a(i*3);
theZoo[i] = a;
}
or yet briefer
{
theZoo[i] = Animal(i*3);
}
(Note the if you would use a std container, you could say theZoo.emplace_back(i*3);, avoiding the copy of Animal.)

Last function not displaying correct output

I am not getting the expected output for the program that I have coded, I know that the implementation for the last function is incorrect. I don't know how to implement this so that it returns the last entry into the array, and doesn't remove it. The second question that I have is on the pop_back function, its supposed to remove last entry pushed into the vector and reduce it by one, and if it's empty do nothing. The way it is now it just reduces the vector by one. Thanks for your help in advance.
Driver
#include <iostream>
#include "vectorHeader.h"
using namespace std;
int main()
{
const char START = 'A';
const int MAX = 12;
// create a vector of doubles
myVector<char> vectD;
// push some values into the vector
for (int i = 0; i < MAX; i++)
{
vectD.push_back(START + i);
}
// remove the last element
vectD.pop_back();
// add another value
vectD.push_back('Z');
// test memory management
myVector<char> vectD2 = vectD;
// display the contents
cout << "\n[";
for (int i = 0; i < vectD2.size() - 1; i++)
{
cout << vectD2[i] << ", ";
}
cout << "..., " << vectD2.last() << "]\n";
system("PAUSE");
return 0;
}
Header
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>
#include <array>
//Declaring constant
const int VECTOR_CAP = 2;
template <class T>
class myVector
{
private:
//Setting data members
T* vectorData;
int cap;
int numElements;
public:
//Default constructor
//Purpose: Creates a vector
//Parameters: None
//Returns: None
myVector();
//Parameterized constructor
//Purpose: Creates a vector capacity of n
//Parameters: None
//Returns: None
myVector(const T&);
//Copy Constructor
//Purpose: Copy data into vector
//Parameters: myVector object
//Returns: None
myVector(const myVector& copy)
{
numElements = copy.numElements;
vectorData = new T [numElements];
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = copy.vectorData[i];
}
}
//Destructor
//Purpose:Deletes any dynamically allocated storage
//Parameters: None
//Returns: None
~myVector();
//Size function
//Purpose: returns the size of your vector
//Parameters: None
//Returns: The size of your vector as an integer
int size() const;
//Capacity function
//Purpose: Returns the capacity of the vector
//Parameters: None
//Returns: Maximum value that your vector can hold
int capacity() const;
//Clear function
//Purpose: Deletes all of the elements from the vector and resets its size to
// zero and its capacity to two; thus becoming empty
//Parameters: None
//Returns: None
void clear();
//push_back function
//Purpose: Adds the integer value n to the end of the vector
//Parameters: Takes a integer to be placed in the vector
//Returns: None
void push_back(const T& n)
{
//If statement to handle if array is full
if (numElements == cap)
{
//Doubling the capacity
cap = cap * VECTOR_CAP;
//Allocating new array
T* newVectorData = new T[cap];
//Copying data
for (int i = 0; i < numElements; i++) newVectorData[i] = vectorData[i];
//Deleting previous data
delete[] vectorData;
//Pointing to new data
vectorData = newVectorData;
}
//Storing data
vectorData[numElements++] = n;
}
//at function
//Purpose: Returns the value of the element at position n in the vector
//Parameters: None
//Returns: Returns your current place with the vector
T& at(std::size_t);
//assignment
//Purpose: Overload the = operator
//Parameters: The two myVector objects we want to assign
//Returns: The assignment
myVector operator=(const myVector&);
void pop_back();
int last();
T& operator[](std::size_t);
};
//Independant Functions
template <typename T>
myVector<T>::myVector()
{
//Setting the cap
cap = VECTOR_CAP;
//Creating the array
vectorData = new T[cap];
//Initializing the value
numElements = 0;
}
template <typename T>
myVector<T>::~myVector()
{
cap = 0;
//Delete array elements
delete[] vectorData;
//Allocate vectorData
vectorData = NULL;
}
template <typename T>
int myVector<T>::size() const
{
return numElements;
}
template <typename T>
void myVector<T>::pop_back()
{
numElements--;
}
template <typename T>
int myVector<T>::last()
{
return cap;
}
template <typename T>
int myVector<T>::capacity() const
{
return cap;
}
template <typename T>
T& myVector<T>::at(std::size_t n)
{
return vectorData[n];
}
template <typename T>
T& myVector<T>::operator[](std::size_t n)
{
return vectorData[n];
}
template <typename T>
myVector<T> myVector<T>::operator=(const myVector& rho)
{
//Test for assingment
if (this == &rho)
{
return *this;
}
//Delete lho
delete[] this->vectorData;
//Creating new array to fit rho data
cap = rho.cap;
this->vectorData = new int[cap];
//Copying data
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = rho.vectorData[i];
}
//Returning myVector object
return *this;
}
template <typename T>
std::ostream& operator<<(std::ostream& out, const myVector<T>& rho)
{
for (int n = 0; n < rho.size(); n++)
{
out << rho.at(n);
}
return out;
}
The last function should look like this:
template <typename T>
T myVector<T>::last()
{
return vectorData[numElements - 1];
}
A function that returns an element from the vector should have the return type the type of the vector elements, i.e. T in your case.
cout has different overloads for char and int. For char it prints the ASCII character of the code provided, for int it returns the code itself. So if your last element is Z and you return an int it would print the ASCII code of Z that is 90.
try this to get a sense of what I am saying:
cout << 'Z' << endl;
cout << (char) 'Z' << endl; // tautological cast as 'Z' is char
cout << (int) 'Z' << endl;
cout << 90 << endl;
cout << (int) 90 << endl; // tautological cast as 90 is int
cout << (char) 90 << endl;
As for pop_back all you have to do is:
if (numElements > 0)
numElements--;
Reason: there is no such thing as deleting memory. A cell of memory always has a value (be it one you set, 0, 1 or garbage). All you have to do is mark it as being available (or not used). That's what you do when you shrink numElements.
If you want to go a step further you could do the opposite of push_back, i.e. relocate the whole vector to a smaller allocated buffer. But this is not advised as these operations (allocating, copying) are expensive and you can do without them (unlike pus_back where you have to get a bigger size)

Class of dynamically resizable C++ string array

I need to create a class called DynamicArray based on the given main.cpp file. However I cannot make it work. The program crashes. I believe it should be the constructor problem. Please see the following codes with comments:
main.ccp
#include <iostream>
#include <dynamicarray.h>
using namespace std;
int main()
{
DynamicArray* arr=new DynamicArray(ARRAY_SIZE);
for (int i=0; i<25; i++) {
arr->add("test");
}
for (int j=0; j<10; j++){
arr->remove();
}
delete [] arr;
arr=NULL;
return 0;
}
dynamicarray.h
#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#define ARRAY_SIZE 5
#include <iostream>
using namespace std;
class DynamicArray
{
DynamicArray* darr;
int del;
int occSize;
int totSize;
public:
DynamicArray();
~DynamicArray();
DynamicArray(int);
void add(string);
void remove();
int totalSize();
int occupiedSize();
DynamicArray operator= (string);
DynamicArray operator= (int);
};
#endif // DYNAMICARRAY_H
dynamicarray.cpp
#include "dynamicarray.h"
DynamicArray::DynamicArray()
{
darr=new DynamicArray[ARRAY_SIZE];
del=0;
occSize=0;
totSize=ARRAY_SIZE;
}
DynamicArray::DynamicArray(int n){
darr=new DynamicArray[n];
del=0;
occSize=0;
totSize=ARRAY_SIZE;
}
DynamicArray::~DynamicArray()
{
delete [] darr;
darr=NULL;
}
//adding s to the next available slot in the array. When the array is full,
//add() will grow the array by another ARRAY_SIZE
void DynamicArray::add(string s){
if (occSize<totSize){
darr[occSize]=s;
occSize++;
}else{
totSize=totSize+ARRAY_SIZE;
DynamicArray* temp=new DynamicArray[totSize];
for (int i=0; i<occSize; i++){
temp[i]=darr[i];
}
darr=temp;
delete [] temp;
temp=NULL;
darr[occSize]=s;
occSize++;
}
}
//remove the element where the index is poining to in the array.
//when there are more than ARRAY_SIZE empty slots left, the delete()
//will shrink the array by another ARRAY_SIZE
void DynamicArray::remove(){
darr[del]=NULL;
del++;
occSize--;
if (del>5){
DynamicArray* temp=new DynamicArray[totSize-ARRAY_SIZE];
int j=del;
for (int i=0; i<occSize; i++){
temp[i]=darr[del];
j++;
}
darr=temp;
del=0;
delete [] temp;
temp=NULL;
}
}
//returning the current max capacity size of the array
int DynamicArray::totalSize(){
return totSize;
}
//returning the number of occupied slots in the array
int DynamicArray::occupiedSize(){
return occSize;
}
DynamicArray DynamicArray::operator= (string s){
*this=s;
return *this;
}
DynamicArray DynamicArray::operator= (int n){
*this=n;
return *this;
}
Of course it crashes, as in the constructor of DynamicArray you create new instances of DynamicArray which calls the constructor which in turn creates new instances of DynamicArray... This infinite recursion will lead to a stack overflow which crashes the program.
If the DynamicArray should by a dynamic array (or vector) of strings, then it should contain an "array" of strings, either std::string objects or of pointers. Like
class DynamicArray
{
private:
char** darr; // The actual array of data
...
};
DynamicArray::DynamicArray(int n)
{
darr = new char*[n];
...
}