Infinite size Stack implementation using pointer to an array - c++

I have been trying to make a infinite size stack using pointer to any int:
//in class:
int* stack;
//In constructor:
stack = new int();
//In deconstructor:
delete stack;
//In Push:
stack(++top) = element;
Is this declaration correct? Can I use this to make an infinite size stack? I run into error when I try to put elements into the stack using such pointer declaration.

It seems you are writing codes in C++? If no, please just ignore my post(face palm).
Firstly, the memory that could be assigned to a program is limited, i.e. no infinite size stack. In C++, there is BSS, Stack and Heap memory. In your case, you have used new operator to assign memory. This in fact effectively means you would like to get a piece of memory in the heap to store your value. Though the size of heap could be dynamically extended, its memory size is still not infinite.
Moreover, it seems what you would like to do in the constructor is to build up an int array with unlimited size. In fact, to declare an array, you may write new int[arraySize] to declare an int array of size, arraySize, in the heap. However, what you have written here is allocating a single int in the heap since the brackets you used are not square, but round. Unfortunately, to create an array, you need to declare its size first (for more details, you may search for stack array and dynamic array). So as to get rid of the size problem, you may use other data structures like std::vector and so forth for simple.
int* stack;
stack = new int();
These 2 statements are to have a pointer pointing to a single int stored in heap memory. Therefore, currently, the stack you make seems to be only able to store an int only.
As for the push function, top is the index of the top int in the stack?
One more thing, in case, what you want to make is creating a pointer to point an int array, and use the array as a stack. Then, you may think about the way to add memory, and have the deconstructor revised to be like this:
delete[] stack;
If you find difficulty in understanding my above paragraphs and have interest in learning more, perhaps you may firstly learn about stack & heap, then, the array declaration as well as its relationship with the memory allocation, followed by the knowledge about pointers.
I am a newbie. Hopefully, I haven't made any mistake in my answer.

First of all new int () creates only a single int not an array of integers therefore you can't do something like stack(++top) = element;.
If you want to create a dynamic array you should use int* stack = new int[size] and delete it with delete [] stack. As you can see the array has a limited size of size but you can resize it when it becomes full. There is no built-in way to resize the array but you can create a new dynamic array with bigger size and copy the old array into it and then remove the old array. But again the stack won't have infinite size since your memory is limited. If the allocation fails an exception will be thrown.
Below is a simple implementation of stack based on a dynamic array.
#include <stdexcept>
using namespace std;
class Stack{
public:
Stack (int _size = 20){
size = _size;
topIndex = 0;
stack = new int [size];
}
~Stack (){
delete [] stack;
}
void resize(){
int new_size = size*2;
int * new_stack;
// try{
new_stack = new int[new_size];
// } catch (std::bad_alloc&) {
// unsuccessful allocation
// }
for ( int i=0; i<size; ++i ){
new_stack[i] = stack[i];
}
delete [] stack;
stack = new_stack;
size = new_size;
}
void push(int element){
if (topIndex + 1 == size){
resize();
}
stack[topIndex++] = element;
}
int top(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
return stack[topIndex-1];
}
}
void pop(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
--topIndex;
}
}
private:
int * stack;
int size;
int topIndex;
};
int main(){
Stack stk;
for ( int i=0;i<50;++i ){
stk.push(i);
cout << stk.top() << endl;
}
for ( int i=0;i<50;++i ){
stk.pop();
cout << stk.top() << endl;
}
}
Note that this is all just for practice and the above implementation is error prone. You should almost always use built-in data structures in practical situations.

Related

Helper function to construct 2D arrays

Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;

Shrinking the size of a dynamically allocated array in C++ [duplicate]

I have created an array pointer as a global variable like this:
T *bag;
bag = new T[size];
I have a method where I insert things into the array; however, if it detects that it will overflow the array, I need to resize the array (without vectors). I've been reading about this question all over stack overflow but the answers don't seem to apply to me because I need the data from the old array copied into the new array. Additionally, if I create a new array of a larger size inside the method and then copy the data over to the new array, once the method ends, the array will disappear, but I need it to be a global variable again so all my methods can see it...How should I proceed?
Thank you
Memory, allocated by new, would not disappear after your method ends.
You can return pointer to a new array by usung reference: void f(int *&ptr, size_t &size).
Also, be aware, that you need to clear memory manually arter you use it. For example:
int* newArray = new int[newSize];
... copying from old array ...
int* temp = oldArray;
oldArray = newArray;
delete[] temp;
To resize an array you have to allocate a new array and copy the old elements to the new array, then delete the old array.
T * p_bag;
p_bag = new T[old_size];
//...
T * p_expanded_bag = new T[new_size];
for (unsigned int i = 0; i < old_size; ++i)
{
p_expanded_bag[i] = p_bag[i];
}
delete[] p_bag;
p_bag = p_expanded_bag;
You could use std::copy instead of the for loop.
The thing you need can do the following things
Automatically handle the resizing when requested size is larger than current array size.
When resizing, they can copy the original content to the new space, then drop the old allocation immediately .
There is a non-global-variable way mechanism they can track the array pointer and the current size.
The thing is very similar to std::vector. If it is not allowed to use, you may need manage a dynamic allocated resource like std::vector on your own. You can reference the implementation in that answer link.
If eventually you need to wrap it in a class, make sure to follow the big 3 rules (5 rules in C++11)
You can use realloc from c if you have array of chars/ints/doubles... or some other fundamental data type or classes with only those variables (eg. array of strings won't work).
http://www.cplusplus.com/reference/cstdlib/realloc/
bag = (T*) realloc(bag, new_size * sizeof(T));
Realloc automatically allocate space for your new array (maybe into the same place in memory) and copy all data from given array.
"The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location."
Example:
#include <stdio.h> /* printf*/
#include <stdlib.h> /* realloc, free */
#include <iostream>
int main()
{
int old_size = 5;
int new_size = 10;
int *array = new int[old_size];
printf("Old array\n");
for (int i=0; i<old_size; i++) {
array[i] = i;
printf("%d ", array[i]);
}
printf("\nArray address: %d\n", array);
array = (int*) realloc(array, new_size * sizeof(int));
printf("New array\n");
for (int i=0; i<new_size; i++)
printf("%d ", array[i]);
printf("\nArray address: %d\n", array);
free(array);
return 0;
}

Revisited: difference between static array and dynamic array in C++?

I'm a beginner for C++ and I saw the post here. However, it is very unclear for me what is the benefit of dynamic array.
One advantage is that one can change the length of a dynamic array, here is the code
int *p = new int[10];
// when run out of the memory, we can resize
int *temp = new int[20];
copy(p, temp); // copy every element from p to temp
delete[] p; // delete the old array
p = temp;
temp = nullptr;
Above is for dynamic allocation, it says the array will be on the heap, and need to manually delete it. However, why not use the static array as follow
int array1[10];
int *p = array1;
// when run out of the memory, we can resize
int array2[20];
copy(array1, array2); // copy every elements from array1 to array2;
p = array2;
In this code, we don't need to delete the array1 since it is on the stack area. Here are my question:
what is the benefit of the dynamic array? It seems for me, resizing is not a big issue. People always say the size of static array are fixed, the size of dynamic array is not fixed. Why the size of dynamic array is not fixed. for example, int p=new int[10], the size of p is fixed.
Thanks a lot.
int array1[10];
int *p = array1;
// when run out of the memory, we can resize
int array2[20];
copy(array1, array2); // copy every elements from array1 to array2;
p = array2;
In whichever function, or inner scope, array1 and array2 get declared these arrays get automatically destroyed when the function or inner scope returns. Full stop.
This is why this is called "automatic scope". The fact that there may be a pointer to one of the arrays is immaterial. The array will be gone and any attempt to dereference that pointer will result in demons flying out of your nose.
So if you had any grand designs to continue using this array, in some form or fashion, after returning from the function where they get declared, too bad. It's not going to happen.
On the other hand, after newing something, as long as you properly track the pointer to the newed object(s) they can be used anywhere else, until they get deleted. This function, another function, anywhere. Even a different execution thread.
Having said all of that, you should not be using new or delete either. You should be using C++ library's containers which will correctly handle all memory allocation, deallocation, and copying, for you. In this case, you are simply reinventing what std::vector already does for you, and it will actually do it, in some ways, far more efficient than you can do easily on your own. You just call resize(), and, presto, your vector is bigger or smaller, as the case may be. And, in all other respects the vector will be indistinguishable from your array. It will be very hard to tell the difference.
So, use C++ library's containers. They are your friends. They want you to do memory allocation correctly, on your behalf. Modern C++ code rarely uses new or delete, any more. It's important to understand how it works, but 99% of the time you don't really need it.
Doing your own dynamic array with new int[20] and delete[] etc, is no doubt good for learning how it all works.
In real C++ programs you would use std::vector. Maybe like this:
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> lines;
std::string line;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
std::cout << "Read " << lines.size() << " lines of input\n";
}
The reason you would use dynamic allocation is so your program can handle any number of lines of any line length. This program can read four lines or 400,000. The std::vector is dynamic. So is std::string.
I have write a code on static and dynamics array, hope this will help.
#include<iostream>
using namespace std;
int main (){
//creating the static array .. rember the syntax of it.
int array[4]= {1,2,3,4}; // size is fixed and can not be changeable at run time.
cout<<"Static Array."<<endl;
cout<<"Printing using index."<<endl;
for(int x=0;x<4;x++){
cout<<"\t"<<array[x];
}
cout<<endl;
cout<<"Printing using pointer."<<endl;
int*ptr= array;
for(int x=0;x<4;x++){
cout<<"\t"<<*ptr++;
}
//delete [] array ;// error, because we can not free the size from stack
// array[6]= {1,2,3,4,5,6}; //Error: We can not change the size of static array if it already defined.
// we can not change the size of the static aray at run time.
cout<<endl;
cout<<"\n\nDynamic Array."<<endl;
int n=4;
//Creating a dynamic Array, remember the systex of it.
int *array2 = new int [n]; // size is not fixed and changeable at run time.
array2[0]= 1;
array2[1]= 2;
array2[2]= 3;
array2[3]= 4;
cout<<endl;
cout<<"Printing using index."<<endl;
for(int x=0;x<4;x++){
cout<<"\t"<<array2[x];
}
cout<<endl;
cout<<"Printing using pointer."<<endl;
int*ptr2= array2;
for(int x=0;x<4;x++){
cout<<"\t"<<*ptr2++;
}
cout<<endl<<endl<<endl;
delete array2; //Size is remove at runtime
cout<<"Chnaging the size of dynamic array at runtime... :)";
// Changing the size of the array to 10.. at runtime
array2 = new int [10]; // Array size is now change to 10 at runtime
array2[0]= 1;
array2[1]= 2;
array2[2]= 3;
array2[3]= 4;
array2[4]= 5;
array2[5]= 6;
array2[6]= 7;
array2[7]= 8;
cout<<endl;
cout<<"Printing using index."<<endl;
for(int x=0;x<7;x++){
cout<<"\t"<<array2[x];
}
// free the memory/ heap
delete [] array2;
return 0;
}
Output

How do I manage to create a vector class in c++?

I was introduced to pointers, I quite get it. but I don't know how to store variables in the vector class using pointers.
Here is what I got from my understanding but how should I complete it?
class Vector{
int size;
int* element;
public:
vector(int x);
int size() const { return size }
};
first, you need to define a value that stores the current size - (number of elements inside the vector) - to be able to add values at the end of the vector.
int curr_vec_size;
also, the actual size of the vector should be saved in a variable to check every time you add a value that allocated memory is not full
int memory_size;
second, you need to allocate memory dynamically by using "new" in the constructor
vector(int size)
{
element = new int[size]; //allocating memory (array of integers)
memory_size= size; //size of allocated memory
curr_vec_size= 0; //no values in the vector
}
then you can make a method that takes an int value and adds it to the dynamic array.
void add_value(int passed_val)
{
if(curr_vec_size < memory_size)
{
element[curr_vec_size]=passed_val; //adding the value in the vector
curr_vec_size ++; //because you have added a new value
}
else
cout<<"vector is full \n";
}
Finally, don't forget to delete the memory you've allocated by using destructors that deletes the pointer to this allocated memory.
vector()
{
delete[] element;
}
To complete what you started, you simply need to use new[] operator to allocate memory to store your int values:
vector(int x)
{
size = x;
element = new int[size]; // this allocates an array of int with a size of "size"
}
Then, you can use element[i] to access i's element of your array.
You'll later need (it's a must) to release allocatd memory to prevent memory leak by implementing a destructor:
~vector()
{
delete [] element;
}
Note that you should (must) also also follow at least the rule of 3 to have you vector be copiable.

Returning structure array value

So I am writing quite a long code and now I came to a problem. How to change structure's arrray's values and get them back to main function.
What I am trying to do this function is: to insert a new value at first array spot(which is 0). The whole for cycle frees the Z[0] and works fine. But I do not know how to return whole CHANGED structure array to the main program. How to do this?
Thank you.
P.S. sorry, for my broken english.
Here are the neccessary parts of the code:
void insertion(Player Z[], int size); //declaration of the funcion
...
int main()
{
int size=5;
Player *Z = new Player[size];
Insertion(Z, size); //calling the function
...
}
void Insertion(Player Z[], int size) //function
{
size++;
Player* temp = new Player[size];
for(int i=0;i<=size-1;i++)
{
temp[i+1]=Z[i];
}
delete [] Z;
Z = temp;
cin>>Z[0].name;
cin>>Z[0].surname;
}
I see many problems in your code.
For example, why are you allocating an array of 5 Players, then deallocating the array and allocating the array again, having the same size? What's the benefit?
You should also note that C++ has call-by-value semantics so the delete[] Z and Z = temp lines have no effect outside of the function you're calling. So, that function should have a signature void Insertion(Player **Z, int size); or Player *Insertion(Player *Z, int size) if you don't want to modify the argument in-place but instead return the new value.
The comments suggested using std::vector. I heavily recommend that approach. If you need a variable-sized container, std::vector is the best choice.
If you however have a reason to do the manual allocations yourself (such as homework assignment) you should use the following strategy: maintain the size of the array in addition to its capacity, and whenever the size would be greater than the capacity, allocate a new array with twice the capacity, copy the contents and deallocate the old array.