Appending a dynamic array and doubling its size upon completion - c++

Create a dynamic array of int with a initial space of 4. Write a function ‘append’ that appends a given value to this array. At any stage, if this function finds the array full it automatically doubles the size of array to accommodate this new value. Also write a function to display all the elements of this array. Write a main to test all these functions.
I made an attempt to solve the above question as given below. However, I am unable to get the correct code. Please help me
#include<iostream>
using namespace std;
void append(int*& array, int val, int n, int r)
{
int i,p;
int *array1;
for (i=r;i<n;i++)
array[i] = val;
if(i==n)
{
p = 2*n;
array1 = new int [p];
}
for(int j =0; j<r/2; j++)
array1[j]= array[j];
append(array1, val, p, p/2);
}
int main()
{
int q,p=0,val, n = 4;
int n1 = p/2;
int *array = new int[n];
while(1)
{
cout<<"Enter 0 to end and 1 to continue";
cin>>q;
while(q!=0)
{
cin>>val;
append(array,val,n,n1);
}
}
return 0;
}
I need to solve this without using "Classes". How shall I do it?

Your function needs to do the following:
1) Be able to check if the current append call will result in an out-of-bounds write attempt. So you need something like (and give variables explanatory names like this) this as the first line in your function:
if (array_size < item_count) {
//double size of array
}
To double the size of the array, you have to make a new array with twice the size, copy all the items over from the old array, DELETE the old array, null the old array's pointer, and somehow update the array_size variable (return to main is one option, a static int counter in the function itself is another). You may have to return a pointer to the new array to main, as well. Or maybe you can just re-address the old pointer to the new array AFTER using that pointer to delete the old array. This is all about avoiding memory leaks. So, try to come up with a method declaration like:
int append(int* arrPtr, int value, int array_size, int item_count)
This particular approach means main is getting sent back the array size as an int after each append. So you need something in main like:
array_size = append(array, val, array_size, item_count);
The tricky part will be when you make the new array:
array_size = 2 * array_size;
int* temp = new int[array_size]
//copy everything over from old array to new using arrPtr and temp
for (int i = 0; i < array_size / 2; i++) {
temp[i] = arrPtr[i]
}
//delete the contents of the old array:
delete[] arrPtr;
//pointer gymnastics to redirect arrPtr to the new array:
arrPtr = temp;
temp = nullptr;
//okay, now you are back out of the conditional and can use item_count to insert the
//value into the array (doubled or not)
arrPtr[item_count] = value;
//don't forget to return array_size, and remember main must track item_count as well.
return array_size;
That's the general gist of it. This is not a complete answer, but should give you enough to work with. Basically, most of your code has to be rewritten, and the above is not a complete solution. Good luck.

After taking cue from Double size of dynamic array I have solved it.
#include<iostream>
using namespace std;
void add_element(int* &array, int &size)
{int count = 0;
while(1)
{
int number;
cout << "What number do you want to add? " << endl;
cin >> number;
if (count == size)
{
int newSize = size * 2;
int *newArr = new int[newSize];
for (int i = 0; i < count; ++i)
{
newArr[i] = array[i];
}
delete[] array;
array = newArr;
size = newSize;
}
array[count] = number;
++count;
int k;
cout<<"Do u want to end, then press 0";
cin>>k;
if(k==0) break;
}
for(int g = 0; g<count; g++)
cout<<array[g]<<'\t';
}
int main()
{
int i,j,k,size;
cin>>size;
int* array = new int [size];
add_element(array, size);
}

Related

Merging two sorted array on third by creating a new array on heap

I have a class array inside which I have declared an array its size and length. I am trying to merge two sorted arrays by creating the third array on the heap and both the sorted array will be merged on the third array. But whenever I create a new arr on heap the compiler gives me this error: request for member '..' in '..' which is of non-class type
class Array
{
public:
int A[10];
int length;
int Size;
};
void display(Array arr)
{
int i;
for(i=0;i<arr.length;i++)
{
cout<<arr.A[i]<<" ";
}
}
void Merge(Array *arr1,Array *arr2)
{
int i,j,k;
i=j=k=0;
int *arr3;
arr3=new int[10];
while(i<arr1->length && j<arr2->length)
{
if(arr1->A[i]<arr2->A[j])
arr3->A[k++]=arr1->A[i++];
else
arr3->A[k++]=arr2->A[j++];
}
for(;i<arr1->length;i++)
{
arr3->A[k++]=arr1->A[i];
}
for(;j<arr2->length;j++)
{
arr3->A[k++]=arr1->A[j];
}
}
int main()
{
Array arr1{{1,3,5,7},4,4};
Array arr2{{2,4,6,8},4,4};
Array *arr3;
arr3=Merge(&arr1,&arr2);
display(*arr3);
return 0;
}
The root cause of all your problems is that you use C-Style array with a magical size 10. Like in int A[10];. This is a major problem and should be avoided in C++.
Additionally, and the same, In C++ we usually do not use raw pointer for owned memories or newand such stuff.
Anyway. The design will never work, if the number of elements in both Array classes is greater then 5. Because then you will definitely get an out of bounds problem.
You must use a std::vector.
So, all bad. But I know that I will hear now, that the teacher said, no vector but new. The teacher should be fired or begin to teach C instead of C++.
Anyway again, I will fix the major bugs for you. But the sorting algorithm will work neither.
So,
If you want to return an Array, then change the signature of your function aand return an Array.
You do want to have a new Array, not new intes. So, please allocate a new Array instead.
Do not forget to release the newed Arrary at then end.
Set size and length of the new array.
Refactor your complete code.
Code example with some fixes:
#include <iostream>
class Array
{
public:
int A[10];
int length;
int Size;
};
void display(Array arr)
{
int i;
for (i = 0; i < arr.length; i++)
{
std::cout << arr.A[i] << " ";
}
}
Array* Merge(Array* arr1, Array* arr2)
{
int i, j, k;
i = j = k = 0;
Array *arr3 = new Array;
while (i < arr1->length && j < arr2->length)
{
if (arr1->A[i] < arr2->A[j])
arr3->A[k++] = arr1->A[i++];
else
arr3->A[k++] = arr2->A[j++];
}
for (; i < arr1->length; i++)
{
arr3->A[k++] = arr1->A[i];
}
for (; j < arr2->length; j++)
{
arr3->A[k++] = arr1->A[j];
}
arr3->length = arr1->length + arr2->length;
return arr3;
}
int main()
{
Array arr1{ {1,3,5,7},4,4 };
Array arr2{ {2,4,6,8},4,4 };
Array* arr3;
arr3 = Merge(&arr1, &arr2);
display(*arr3);
delete[]arr3;
return 0;
}

Errors with dynamic Array created with new after passed to resize function

I am trying to implement a dynamically created array using new that I want to resize but the resize action is not working correctly.
This is an exercise on dynamic arrays, so I need dynamic arrays using new and not std::vector.
Here is my code :
int main ()
{
// Build an application here
int length = 0;
int size = 0;
int input;
bool endAdding = false;
cout << "Please enter the length of the new array : ";
cin >> length;
int* oPtrDynamicArray = CreateDynamicArray (length, size);
do
{
cout << "Add an element (0 to quit) : " << endl;
cin >> input;
cout << endl << endl;
if (input == 0){
endAdding = true;
}
else
{
InsertElement(oPtrDynamicArray, input, size, length);
}
cout << "The array contains : " << endl;
for (int i = 0; i < size; i++)
{
cout << i << ": [" << oPtrDynamicArray[i] << "]" << endl;
}
} while (!endAdding);
DeleteDynamicArray (oPtrDynamicArray, size);
}
int *CreateDynamicArray (int capacity, int &size)
{
size = 0;
return new int[capacity];
}
void DeleteDynamicArray (int *dynamicArray, int &size)
{
delete[] dynamicArray;
dynamicArray = nullptr;
size = 0;
}
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int ** newArray = new int*[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = dynamicArray[i];
}
*dynamicArray = *newArray;
delete[] newArray;
newArray = nullptr;
}
The problem is that the array is passed to my InsertElement() function and then to ResizeDynamicArray() only if capacity <= size, but the array passed to the first function, is passed with good values, but with abnormal pointers in the array.
Example :
For an array of 3, I have :
array[0] = 1 --> adress 0x0004e300 containing value 1
array[1] = 2 --> adress 0x00000003 containing ???
array[2] = 3 --> adress 0x008ffb24 containing value 2
I really don't understand, it would be really great if someone could explain my error :/.
The problem is here
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
when you call ResizeDynamicArray you are changing the dynamicArray pointer declared as a parameter to InsertElement. You are not changing the oPtrDynamicArray pointer in main.
If you want to make this work you need to change InsertElement to take a double pointer (just like ResizeDynamicArray)
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (dynamicArray, size+1);
}
(*dynamicArray)[size] = element;
size++;
}
Or you could do the easy thing and just use std::vector<int>.
EDIT now that I look at it your ResizeDynamicArray function I see that function is completely wrong as well. It's clear that you have some learning to do with pointers
Here's how ResizeDynamicArray should be
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int * newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
You're not the first newbie to fail to understand pointers. Have a good look at the code above and compare it with your code. The main difference is that my code using a pointer to change what is being pointed to. Your code tried to change the pointer itself, which is incorrect. It's confusing because what is being pointed to is another pointer (the dynamic array).
There are several issues in your code:
First, in ResizeDynamicArray, you allocate an array of pointers to ints, not an array of ints. int ** newArray = new int*[newCapacity] should be int *newArray = new int[newCapacity].
Second, once you have fixed that, you need to write *dynamicArray = newArray;;
but you should free the old array before you assign the pointer to the new memory block.
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int *newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
Third, you since InsertElement may call ResizeDynamicArray (which will give you back a new memory block), you need to alter the originally passed pointer. So you need to pass a pointer to a pointer int the function, just as you did with ResizeDynamicArray:
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
adapt the body accordingly then.
I know the question is already answered but not the why.
You have to keep in mind that pointers are passed to functions by value.
The pointer value, the address it points to, is lost when the function ends.
But you are still able to change the value stored at the address it points to by dereferencing the pointer.
To pass be able to change the pointer value, the address it points to, inside a function, you have to pass a pointer to a pointer. In this case passing a double pointer is synonym for passing a pointer to a function by reference.
void Foo(int **ptr)
{
// Don't use ptr, changes are lost after function end as ptr is a local copy
// Use *ptr to change the value of the pointer you passed to the function.
// Use **ptr to change the value at the address the pointer you passed to the funcion points to
}
In this case you can change the pointer value, the address it points to, by dereferencing the double pointer once. Which applies to above answers.

A global static array in C++

I've got something like this:
static int n = 0; // global static int
int *arr = new int[n]; // global int*
int randToArray(int arr[], int min, int max) {
srand(time(NULL));
for(int i = 0; i <= n; i++) {
arr[i] = (rand() % max + min);
}
}
void printArray() {
if(n) {
for(int i = 0; i < n; i++)
cout << arr[i] << endl;
} else
cout << "The array hasn't been drawed yet.";
}
And then in the main function I have a menu with a switch and options for getting random numbers and printing the array:
switch(option) {
case 1:
cout << "Set the size of the array: ";
cin >> n;
randToArray(arr, 1, 99);
break;
case 2:
printArray();
wait();
break;
}
I need my array to be available globally in order to use in several other functions.
Everything works except one thing: when I want to print the array I get working properly only 8 first elements. Then the terminal shows up some very large numbers.
That's because you use
static int n = 0;
then allocate memory for zero elements.
Change the line static int n = 256; for example, to allocate memory for 256 elements.
Or, if you read n after, allocate the memory AFTER you have read n. That is, declare the array globally first (technically a pointer), as int *arr;, then
arr = new int[n];
after cin >> n;
static is a much overloaded keyword.
The way you use it, it means translation-unit-local.
Also, you don't have any global array in your code, only a pointer initialized to point to the beginning of an allocation of 0 ints.
That allocation won't be changed if you later change n.

Doubling the Size of a C++ Array

The following snippet of code is my attempt to increase the size of an array by a factor of two. I am having several problems with it. Most importantly, should I be calling delete on my original array?
void enlarge(int *array, int* dbl int size) {
for (int i = 0; i < size; i++)
dbl[i] = array[i];
delete array;
array = dbl;
}
You have a few problems:
Modifying array only modifies the local copy of the pointer. You need to take a reference-to-pointer if you want the modification to be observed by the calling code.
You need to use delete[] when deleting things allocated with new[].
You attempt to copy too many items, and in so doing you overrun the original array.
void enlarge(int *& array, int size) {
// ^
// Use a reference to a pointer.
int *dbl = new int[size*2];
for (int i = 0; i < size; i++) {
// ^
// Iterate up to size, not size*2.
dbl[i] = array[i];
}
delete[] array;
// ^
// Use delete[], not delete.
array = dbl;
}
However, I would strongly suggest using std::vector<int> instead; it will automatically resize as necessary and this is completely transparent to you.
keyword double cannot be used as variable name, and previous array must be deleted before new allocation get assigned to same pointer, and loop should copy size no of items from prev array (not 2 * size)
void enlarge(int **array, int size) {
int *d = new int[size*2];
for (int i = 0; i < size; i++)
d[i] = *array[i];
delete [] *array;
*array = d;
}
if previous array was int *arr, and size is the currentsize of the array arr, call should be as: enlarge(&arr, size)

Unitialized local variable and help correcting

I am learning about pointers and the new operator in class.
In my readArray function I am to read in a size. Use the size to dynamically create an integer array. Then assign the array to a pointer, fill it, and return the size and array.
I believe I've gotten that part corrected and fixed but when I try to sort the array, i get the error "uninitialized local variable temp used."
The problem is though I get that error when I am trying to intialize it.
Any help appreciated thank you. Seeing my errors is very helpful for me.
#include <iostream>
using namespace std;
int* readArray(int&);
void sortArray(int *, const int * );
int main ()
{
int size = 0;
int *arrPTR = readArray(size);
const int *sizePTR = &size;
sortArray(arrPTR, sizePTR);
cout<<arrPTR[1]<<arrPTR[2]<<arrPTR[3]<<arrPTR[4];
system("pause");
return 0;
}
int* readArray(int &size)
{
cout<<"Enter a number for size of array.\n";
cin>>size;
int *arrPTR = new int[size];
for(int count = 0; count < (size-1); count++)
{
cout<<"Enter positive numbers to completely fill the array.\n";
cin>>*(arrPTR+count);
}
return arrPTR;
}
void sortArray(int *arrPTR, const int *sizePTR)
{
int *temp;
bool *swap;
do
{
swap = false;
for(int count = 0; count < (*sizePTR - 1); count++)
{
if(arrPTR[count] > arrPTR[count+1])
{
*temp = arrPTR[count];
arrPTR[count] = arrPTR[count+1];
arrPTR[count+1] = *temp;
*swap = true;
}
}
}while (swap);
}
You make temp an int pointer (uninitiialized), and then set the thing it points at (anything/nothing) to arrPTR[ccount]. Since you are using temp only to swap, it should be the same type as those being swapped, in this case: an int.
If it absolutely must be a pointer (there is no good reason for this, it's slow, confusing, adds potential for errors, and adds potential for memory leaks):
int *temp = new int; //make an int for the pointer to point at
bool *swap = new bool; //make an bool for the pointer to point at
do
{
//your code
}while (swap);
delete temp;
delete swap;
You declared temp as a pointer. You need to allocate it on the heap before dereferencing and assigning to it later. However perhaps a variable on the stack would be preferable?
FYI: You should be aware of the memory leak in readArray as well which is leaving callers responsible for calling delete []
Edit: I hope this will help clear up some of the other problems.
#include <iostream>
int* readArray(int&);
void sortArray(int*, int);
int main ()
{
int size(0); // use stack when possible
int *arrPTR = readArray(size);
sortArray(arrPTR, size);
// arrays are zero based index so loop from 0 to size
for (int index(0); index < size; ++index)
std::cout << arrPTR[index];
delete [] arrPTR; // remember to delete array or we have a memory leak!
// note: because we did new[] for an array we match it with delete[]
// if we just did new we would match it with delete
system("pause");
return 0;
}
int* readArray(int& size)
{
std::cout << "Enter a number for size of array.\n";
std::cin >> size;
int *arrPTR = new int[size]; // all news must be deleted!
// prefer pre-increment to post-increment where you can
for(int count(0); count < size; ++count)
{
std::cout << "Enter positive numbers to completely fill the array.\n";
std::cin >> arrPTR[count];
}
return arrPTR;
}
// passing size by value is fine (it may be smaller than pointer on some architectures)
void sortArray(int *arrPTR, int size)
{
// you may want to check if size >= 2 for sanity
// we do the two loops to avoid going out of bounds of array on last iteration
for(int i(0); i < size-1; ++i) // the first to compare (all except last)
{
for(int j(i+1); j < size; ++j) // the second to compare (all except first)
{
// do comparison
if (arrPTR[i] > arrPTR[j]) // from smallest to biggest (use < to go from biggest to smallest)
{
// swap if needed
int temp(arrPTR[i]); // put this on stack
arrPTR[i] = arrPTR[j];
arrPTR[j] = temp;
}
}
}
}
temp is a "pointer to int, which you're not initializing. When you say *temp = ... you're actually assigning to whatever temp happens to be pointing, but since you haven't told it what to point to, it can write pretty much anywhere in the address space of your program.
Because of the way you're using them, it seems that temp and swap shouldn't be pointers at all, just a plain int and bool.
You didn't initialize the temp pointer do when you dereference it you are writing to a random part of memory. Temp doesn't need to be a pointer, it can just be an int. Just replace EVERY instance of *temp with temp.