How can i create push_back function of dynamic array? - c++

Im trying to create this and add push back functionality. How can i do it? I came up with this code but im very confused for 2 days because it gives this output - | -842150451 | -842150451 | -842150451 | -842150451 | -842150451 | -842150451 | -842150451 | -842150451
I will be thankful if someone can tell me how this function push_back should look or at least point me in the right direction. Also i would be thankful if you tell me where this code is doing wrong?
struct IntArray{
private:
int k;
int* first_cell;
int size; // currently occupied elements
int capacity = 8; // size of the allocated memory
public:
void create() {
first_cell = (int*)malloc(capacity * sizeof(int));
}
void random_numbers_fill(int limit) {
srand(time(NULL));
for (k = 0; k < capacity; k++) {
first_cell[k] = rand() % limit;
}
}
void push_back(int number) {
if (size == capacity) {
int* new_arr;
capacity *= 2;
new_arr = (int*)malloc(capacity * sizeof(int));
for (k = 0; k < capacity; k++) {
new_arr[k] = first_cell[k];
}
free(first_cell);
first_cell = new_arr;
first_cell[size] = number;
size++;
}
}
void print() {
for (k = 0; k < capacity; k++) {
printf("| %d ", first_cell[k]);
}

First, create() should be changed into an actual constructor. And you are missing a destructor to free the array, as well as copy/move constructors and copy/move assignment operators to manage the array (per the Rule of 3/5/0).
Second, you should be using new[] instead of malloc().
Third, regarding your push_back(), it is not a bad attempt, but it is buggy. You are not adding the number to the array at all if the current size is less than the current capacity (and your constructor is not initializing size at all). And when you do resize + copy the array, you are copying too many ints from the old array. The old array is size elements, but you are trying to copy the newly increased capacity elements from it.
With that said, try something more like this instead:
#include <iostream>
#include <algorithm>
#include <utility>
class IntArray{
private:
int* first_cell = nullptr;
int size = 0; // currently occupied elements
int capacity = 8; // size of the allocated memory
public:
IntArray()
{
first_cell = new int[capacity];
}
IntArray(const IntArray &src)
: size(src.size), capacity(src.capacity)
{
first_cell = new int[capacity];
std::copy_n(src.first_cell, size, first_cell);
}
IntArray(IntArray &&src)
: first_cell(src.first_cell), size(src.size), capacity(src.capacity)
{
src.first_cell = nullptr;
src.size = src.capacity = 0;
}
~IntArray()
{
delete[] first_cell;
}
IntArray& operator=(IntArray rhs)
{
IntArray temp(std::move(rhs));
std::swap(first_cell, temp.first_cell);
std::swap(size, temp.size);
std::swap(capacity, temp.capacity);
return *this;
}
void push_back(int number)
{
if (size == capacity)
{
int new_cap = capacity * 2;
int* new_arr = new int[new_cap];
for (int k = 0; k < size; ++k) {
new_arr[k] = first_cell[k];
}
delete[] first_cell;
first_cell = new_arr;
capacity = new_cap;
}
first_cell[size] = number;
++size;
}
void print() const
{
for (int k = 0; k < size; ++k) {
std::cout << "| " << first_cell[k] << " ";
}
}
};
That being said, you should just get rid of your manual array and use std::vector<int> instead, as it handles all of these details for you, eg:
#include <iostream>
#include <vector>
class IntArray{
private:
std::vector<int> vec;
public:
IntArray()
{
vec.reserve(8);
}
void push_back(int number)
{
vec.push_back(number);
}
void print() const
{
for (int number : vec) {
std::cout << "| " << number << " ";
}
}
};

You never initialize size in create.
Your push_back has two problems. You don't copy the number that is pushed unless you grow the array (the last two statements should be outside the if block), and the condition in the for loop should compare with size, not capacity.
print also has the wrong condition in the for loop.

Related

Vector resize function not working properly c++

I have been making a custom vector class, however I have been bumping into a problem. The problem being that my vector just won't resize, the size stays 0.
Anyone know what the problem is?
Thanks in advance!
void resize(const int newSize) {
// If size is zero, give error
if (newSize < 0) {
throw std::out_of_range("Vector");
}
// If the given size is smaller than the size that it is now, just ignore
else if (newSize < capacity) {
return;
}
// Else, make a new array and copy everything over
T* newArr = new T[newSize];
for (int i = 0; i < capacity; i++) {
newArr[i] = data[i];
}
delete[] data;
capacity = newSize;
data = newArr;
}
EDIT 1:
Here is the push_back function where resize is needed:
template <typename T> void pushBack(Vector<T>& vector, T& value){
unsigned int oldSize = vector.size();
vector.resize(oldSize+1);
vector.at(oldSize) = value;
}
EDIT 2:
Here are the vector deffinitions:
Vector(const int newSize) {
if (newSize < 0) {
throw std::out_of_range("Vector");
}
data = new T[newSize];
capacity = newSize;
actualSize = 0;
}

Write a dynamic array

I want to write a program that can use a dynamic array.
A size is to be passed via the constructor and as soon as this size is reached, a new array is generated in which the previous values are copied into it.
For this, I overloaded the [] operator. The program seems to work at first glance.
But after I tried to implement an array with the size 100 and to save 20000 elements here, different numbers are output.
At the first run, more than 7000 numbers were displayed. After another run over 1800. However, never the desired 20000.
What could be the reason for this?
#include <iostream>
using namespace std;
template<class T>
class Container{
public:
T *dynamicArray;
private:
T *newArray;
int size;
public:
Container(int size){
this->size=size;
dynamicArray=new T[size];
}
T operator[] (unsigned long index){
if(index>size-1){
newArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
newArray[i]=dynamicArray[i];
}
delete[] dynamicArray;
dynamicArray=newArray;
delete[] newArray;
}
return dynamicArray[index];
}
};
int main()
{
Container <int> dArray(100);
for(int i=1; i<20000; i++){
dArray.dynamicArray[i]=i;
cout << dArray.dynamicArray[i] << "\n";
}
return 0;
}
Thank you!
first , this code didn't call the overloaded [] operator function , its just using default operator [] of type T array , and it never allocate any memory , you can output at allocate memory position
dArray.dynamischesArray[i]=i;
cout << dArray.dynamischesArray[i] << "\n";
and there it some error logic in the overloaded [] operator function
T operator[] (unsigned long index){
if(index>size-1){
neuesArray=new T[size+(index-size)];
T i;
for(i=0; i<(size+(index-size)); i++){
neuesArray[i]=dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray=neuesArray;
//delete[] neuesArray; cannot deleted ,course error
size = index + 1; //keep size sync real size
}
return dynamischesArray[index];
}
this is modified code can be run correct :
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Container {
public:
T *dynamischesArray;
private:
T *neuesArray;
int size;
public:
Container(int size) {
this->size = size;
dynamischesArray = new T[size];
}
T& operator[] (unsigned long index) {
if (index > size - 1) {
cout << "allocate :" << index<<"\n";
neuesArray = new T[index+1];
unsigned long i;
for (i = 0; i < size; i++) {
neuesArray[i] = dynamischesArray[i];
}
delete[] dynamischesArray;
dynamischesArray = neuesArray;
//delete[] neuesArray;
size = index+1;
}
T&ret = dynamischesArray[index];
//return dynamischesArray[index];
return ret;
}
};
int main()
{
Container <int> dArray(100);
for (int i = 1; i < 20000; i++) {
dArray[i] = i;
cout <<"i="<<i<<" "<< dArray[i] << "\n";
//dArray.dynamischesArray[i] = i;
//cout << dArray.dynamischesArray[i] << "\n";
}
return 0;
}
this is result

Code runs when in main() but gives error when in function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am writing a dynamic matrix class that stores each non-zero value as a List of 3 elements [row,column,value]
I made a dynamic array class called "List", and class"Matrix" a List of list pointers.
My code to transpose the Matrix works:
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
it works when written directly in main() but gives error when in stand alone function. can anyone explains why and how to fix it?
Full code:
#include <iostream>
using namespace std;
class List //a dynamic int pointer array
{
private:
int capacity;
int numOfElem;
int *arr;
//initialize all values in capacity to 0
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = 0;
}
}
//double the capaicty, then initialize
void expand()
{
capacity *= 2;
int *tempArr = new int[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
List()//constructor
{
capacity = 10;
numOfElem = 0;
arr = new int[capacity];
}
~List()//destrcutor
{
delete[] arr;
}
//add int to the end of List
void append(int newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
//Copy all element of an input list to the end of List
void copy(List list)
{
for (int i = 0; i < list.getNumOfElem(); i++)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = list.getAt(i);
}
}
//get reference of the int at an index in te list
int* getAddress(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return &arr[index];
}
//change the value of at specific index
void set(int index, int value)
{
arr[index] = value;
}
//get int at an index in te list
int getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
void displayList()
{
for (int i = 0; i < numOfElem; i++)
{
cout << arr[i] << " ";
}
}
};
class Matrix //a List of list pointers
{
private:
int capacity;
int numOfElem;
List* *arr;
void initialize(int from)
{
for (int i = from; i < capacity; i++)
{
arr[i] = new List;
}
}
void expand()
{
capacity *= 2;
List* *tempArr = new List*[capacity];
for (int i = 0; i < numOfElem; i++)
tempArr[i] = arr[i];
delete[] arr;
arr = tempArr;
initialize(numOfElem);
}
public:
Matrix()
{
capacity = 10;
numOfElem = 0;
arr = new List*[capacity];
}
~Matrix()
{
delete[] arr;
}
void append(List* newElement)
{
if (numOfElem >= capacity)
expand();
arr[numOfElem++] = newElement;
}
void set(int index, List* value)
{
arr[index] = value;
}
List* getAt(int index)
{
if (index < 0 || index >= numOfElem)
throw ("Out of bounds exception!!!");
return arr[index];
}
int getNumOfElem()
{
return numOfElem;
}
};
void transpose(Matrix tripleList)
{
for (int i = 0; i < tripleList.getNumOfElem(); i++)
{
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
cout << "\n";
}
}
int main()
{
int m, n, input;
cout << "Please enter the number of rows and columns of the matrix :\n";
cin >> m >> n;
Matrix tripleListMatrix;
int k = 0;
cout << "Please enter the matrix : \n";
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> input;
if (input != 0)
{
tripleListMatrix.append(new List);
(*(tripleListMatrix.getAt(k))).append(i + 1);
(*(tripleListMatrix.getAt(k))).append(j + 1);
(*(tripleListMatrix.getAt(k))).append(input);
k++;
}
}
}
cout << "The triple list of matrix is:\n";
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
cout << "\n\n";
//transpose(tripleListMatrix);
//the code below is the same as in the function transpose but transpose gives error
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
List* list = new List;
(*list).copy(*(tripleListMatrix.getAt(i)));
int temp = (*list).getAt(0);
(*list).set(0, (*list).getAt(1));
(*list).set(1, temp);
(*list).displayList();
//cout << "\t" << list;
cout << "\n";
}
cout << "\n\n";
//checking that tripleListMatrix is unchanged
for (int i = 0; i < tripleListMatrix.getNumOfElem(); i++)
{
(*(tripleListMatrix.getAt(i))).displayList();
cout << "\n";
}
return 0;
}
List* *arr;
When you call transpose(), it makes a copy Matrix because you're not passing by reference. That copy just has a copy of the address for your List, not it's own List object. When the destructor runs on the copy, it clears up the allocated memory, but the original Matrix object in main still points to that same memory. When that object goes away, its destructor tries to free the same memory again and that's bad.
You probably meant:
void transpose(Matrix const & tripleList)
So that no copy is made when calling transpose(), but you should also explicitly delete the copy construtor of Matrix so it cannot be called
Matrix(Matrix const &) = delete;
or make an explicit Matrix copy constructor that makes a deep copy of the memory.

Doesn't work Copy Assignment Operator

In my code, I am having trouble on my copy assignment operator. When I try to execute "=" operator in my main(), the content of my source array (numArr) is not copied to my destenation array (numArr2).
Then, for my doubleCap() function, I am try to create a bigger array of double size once my original array is full. However, if I insert delete[] newArr, the compiler will output some random numbers in my array.
This is my code in .cpp
#include <iostream>
#include "NumList.h"
using namespace std;
//Default Constructor
NumList::NumList()
{
//Actual elements stored in the array
size = 0;
//Max capacity of the array
capacity = 1;
numList = new int[capacity];
}
//Destructor
NumList::~NumList()
{
delete[] numList;
}
//Copy Constructor
NumList::NumList(const NumList& anotherNumList)
{
capacity = anotherNumList.capacity;
size = anotherNumList.size;
numList = new int[capacity];
for (int i = 0; i < size; ++i)
{
numList[i] = anotherNumList.numList[i];
}
}
//Copy Assignment Operator
NumList& NumList::operator= (const NumList& anotherNumList)
{
//Check if it is self-assigning
if (this == &anotherNumList)
return *this;
//Get rid of the old data
delete[] numList;
this->capacity = anotherNumList.capacity;
//Create and copy to the new array
numList = new int[capacity];
for (int i = 0; i < anotherNumList.size; ++i)
{
numList[i] = anotherNumList.numList[i];
}
return *this;
}
void NumList::print()
{
for (int i = 0; i < size; ++i)
{
cout << numList[i] << " ";
}
cout << endl;
}
void NumList::doubleCap()
{
capacity = capacity * 2;
//Create a new array when the capacity is full
int * newArr = new int[capacity];
for (int i = 0; i < size; ++i)
{
newArr[i] = numList[i];
}
//Let numlist points to the new array
numList = newArr;
//delete[] newArr; <--
}
void NumList::insertEnd(int val)
{
//Double the capacity of the list
if (size == capacity)
{
doubleCap();
}
numList[size] = val;
++size;
}
void NumList::insertAt(int val, int index)
{
if (index < 0 || index > capacity)
{
cout << "The index is out of range." << endl;
}
else
{
//Double the capacity of the list
if (size == capacity)
{
doubleCap();
}
for (int i = (size-1); i >= index; i--)
{
numList[i + 1] = numList[i];
}
numList[index] = val;
++size;
}
}
This is my code in main
#include <iostream>
#include <string>
#include <algorithm>
#include "NumList.h"
using namespace std;
int main()
{
NumList numArr;
NumList numArr2;
numArr.insertEnd(10);
cout << "List 1 after inserting 10: ";
numArr.print();
numArr2 = numArr;
NumList numArr3(numArr);
numArr.insertEnd(11);
numArr.insertEnd(12);
numArr.insertAt(5, 0);
cout << "List 1: ";
numArr.print();
cout << "\nPrint the list 2 of int: ";
numArr2.print();
cout << "\nPrint the list 3 of int: ";
numArr3.print();
system("pause");
return 0;
}
Output without line "delete[] newArr;",
List 1 after inserting 10: 10
List 1: 5 10 11 12
Print the list 2 of int:
Print the list 2 of int: 10
Press any key to continue . . .
Output with line "delete[] newArr;",
List 1 after inserting 10: 10
List 1: 5 -572662307 -572662307 12
Print the list 2 of int:
Print the list 2 of int: 10
Press any key to continue . . .
You are trying to delete the wrong thing. In doubleCap() you have 2 arrays, the member and the new on you create that has more space. The one that has more space is the one you want to keep so you can't delete it. What you need to do is delete the original array and then assign to it the new one. That makes the function look like
void NumList::doubleCap()
{
capacity = capacity * 2;
//Create a new array when the capacity is full
int * newArr = new int[capacity];
for (int i = 0; i < size; ++i)
{
newArr[i] = numList[i];
}
delete [] numList; // get rid of the old array
//Let numlist points to the new array
numList = newArr;
}
You are also missing the assignment of anotherNumList.size to this->size in your operator =. That causes the copied list to have the wrong size after assignment.

ArrayStack size

I had this task in C++ where I had to implement a Stack only using arrays (and not using things like Vectors). The teacher gave us an interface to follow and some code to test our ArrayStack on. My problem is that when I create a stack, fill it with 100 elements then empty it the size is 4 (i set 4 for a minimum) and when the teacher code do the same (in the testStack function) the same check fails.
Heres my code:
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
template<typename T>
class Stack {
public:
// Adds new element to the top of the stack
virtual void push(T x) = 0;
// Returns the top element AND removes it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T pop() = 0;
// Returns the top element but does NOT remove it from the stack
// If the stack is empty use 'throw std::out_of_range("<human_friendly_message>");'
virtual T top() = 0;
// Returns the current number of elements in the stack
virtual int getSize() = 0;
// Returns the current capacity of the underlying data storage (array)
virtual int getCapacity() = 0;
// Returns true if the stack has no elements and false otherwise
virtual bool isEmpty() = 0;
};
template<typename T>
class ArrayStack : public Stack<T>{
private:
T* data;
int arraysize;
int N;
void resize(int capacity)
{
T* copy = new T[capacity];
for (int i = 0; i < N; i++)
copy[i] = data[i];
T* p = data;
data = copy;
delete [] p;
}
public:
ArrayStack(){
N = 0;
data = new T[4];
arraysize = 4;
}
ArrayStack(int n){
if (n < 1) n = 1;
N = 0;
data = new T[n];
arraysize = n;
}
bool isEmpty(){ return N == 0; }
void push(T x)
{
if (N == arraysize)
{
resize(2 * arraysize);
arraysize *= 2;
}
data[N] = x;
N++;
}
T pop()
{
if (isEmpty()){
throw out_of_range("Can't pop on empty stack");
}
else{
N--;
T k;
k = data[N];
if (N > 0 && N == arraysize / 4 && arraysize/2>=4)
{
resize(arraysize / 2);
arraysize /= 2;
}
return k;
}
}
T top()
{
if (isEmpty()) throw out_of_range("Can't top on empty stack");
return data[N - 1];
}
int getCapacity()
{
return arraysize;
}
int getSize()
{
return N;
}
~ArrayStack()
{
delete [] data;
}
};
template<class T>
void testStack(Stack<T> *& stack, int cap = 128) {
for (int i = 0; i < 100; i++) {
stack->push(i);
assert(stack->top() == i);
}
assert(stack->getCapacity() == cap);
assert(stack->getSize() == 100);
for (int i = 99; i >= 0; i--) {
assert(stack->top() == i);
stack->pop();
}
assert(stack->getCapacity() == 4);
assert(stack->isEmpty());
}
int main() {
try {
Stack<int> * stackI = new ArrayStack<int>();
testStack(stackI);
delete stackI;
Stack<float> * stackF = new ArrayStack<float>(1);
testStack(stackF);
delete stackF;
Stack<double> * stackD = new ArrayStack<double>(65536);
testStack(stackD, 65536);
delete stackD;
Stack<string> * stackS = new ArrayStack<string>();
stackS->push("string1");
stackS->push("string2");
stackS->push("string3");
stackS->push("string4");
for (int i = 0; i < 4; i++) {
stackS->pop();
}
assert(stackS->isEmpty());
cout << "All tests passed!" << endl;
}
catch (std::exception & ex) {
cout << ex.what() << endl;
}
return 0;
}
As you may have noticed, the problem occurs with the last stack, the one with an initial capacity of 65536.
If you print the capacity just before the failed assertion, you will notice that it's 65536.
It looks like the stack hasn't been resized at all.
Looking at your conditions for when to shrink the storage, there is a required condition that N == arraysize / 4.
Since N doesn't become greater than 100, and 65536 / 4 is 16384, this condition will never be true.
Replacing == with <= takes care of it:
N <= arraysize / 4