array manipulation - c++

So i'm trying to avoid using vectors to do this, i know it would make it easier, but i'm trying to better my understanding of pointers and arrays. So is there a way to expand and shift an array without using the vectors? Here is what i have so far:
int *expand(int *&arr, int size)
{
int *newArray;
size = size * 2;
newArray = new int[size * 2];
for (int index = 0; index < size; index++)
newArray[index] = arr[index];
return newArray;
}

The simplest way to do what you want would be the standard library function realloc.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
int* new_array = (int*) realloc (old_array, new_size * sizeof(int));
Note the *sizeof(int). That's important :)
realloc makes sure the contents of *old_array* can be found in *new_array*(it's either the same pointer, or the contents are copied). See the link for details.

In c++, try to avoid raw pointers. But since this is an exercise, this is a c++ way :
int *expand(int *&arr, int size)
{
int *newArray = new int[2*size];
std::copy( &arr[0],&arr[size], &newArray[0] );
// delete [] arr; // need to delete?
return newArray;
}
To do in place :
void expand(int *&arr, int size)
{
int *newArray = new int[2*size];
std::copy( &arr[0],&arr[size], &newArray[0] );
delete [] arr;
arr = newArray;
}

To do it manually, you need to copy the old data with the size of the original array, right now you're walking off the end of the original array.
Try this:
int *expand(int *&arr, int size)
{
int *newArray;
newArray = new int[size * 2];
for (int index = 0; index < size; index++)
newArray[index] = arr[index];
return newArray;
}

You're allocating twice as much memory as you need.
You're not deleting the old array.
You're not assigning the new pointer to arr - passing it as reference indicates that's what you intended - or that you intended to delete[] arr and assign 0 to it.

See this link for a method that uses memcpy instead of looping through individual items.
int *expand(int *&arr, int size)
{
size_t newSize = size * 2;
int* newArr = new int[newSize];
memcpy( newArr, arr, size * sizeof(int) );
size = newSize;
delete [] arr;
arr = newArr;
}

Since you aren't changing the value of arr inside the function, there's no need to pass the address by reference. If you did mean to change the value, you need to add a new line of code before the return newArray:
arr = newArray;
If the typical calling pattern is
arr = expand(arr, arr_size);
then you'll also need to watch out for options that ignore aliasing. And you'll have to make assumptions within expand that size is always doubled, and keep track of that yourself outside of it.
Also, your code has a terrible bug. size is doubled, and then used as the array limit for the source array. Then it leaks the memory that was previously allocated for arr. This is a good reason why people use std::vector. :-) Most of the bugs are out of that library, by now.
void expand_in_place(int *&arr, int& size)
{
const new_size = size * 2;
int *new_array = new int[new_size];
for (int index = 0; index < size; index++)
new_array[index] = arr[index];
delete[] arr;
arr = newArray;
size = new_size;
}
If you were using malloc and free instead of new [] and delete [], you could use realloc.

Related

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)

How do I make function that needs to do this?

I am working in c++ with structs and dynamic allocation,and i need to make function that automatically increases the size of array:
structType * array=new structType[max];
and i can't use `vectors'. Does anybody knows how to do this?
Following my comment, here's the implementation:
void resizeArray(structType*& oldArray, size_t oldSize, size_t newSize) {
structType* newArray = new structType[newSize];
for (size_t i = 0; i < std::min(oldSize, newSize); ++i)
newArray[i] = oldArray[i];
delete[] oldArray;
oldArray = newArray;
}
structType* array = new structType[max];
resizeArray(array, max, max + 10);
Note that the code above is not exception safe: if newArray[i] = oldArray[i]; throws then you will leak memory. But I believe this is enough to get you started.

arr is used before its value is set

Hello I have a generate array method:
void generateArray(double *data, int count) {
for (int i = 0; i < count; i++)
data[i] = rand() / ((rand() + rand()) / 2.0 + 1);
}
and I have below main
int main(void) {
double *arr;
generateArray(arr,40000);
cout << arr[0];
return 0;
}
it says arr is used before its value is set why? Why does not genearate array fills it? How can i fix this problem?
double *arr;
This only gives you a pointer. You haven't allocated any doubles for it to point at and you haven't initialised the pointer to actually point anywhere. Here, you'll find it easier to declare an array of the appropriate size instead:
double arr[40000];
Passing arr as you are currently doing will perform array-to-pointer conversion and it will work as expected.
However, an array of 40000 doubles is a pretty large object to have on the stack. You may prefer to dynamically allocate your array with double* arr = new double[40000];, but you would need to make sure you do delete[] arr; when you are done with it to avoid memory leaks. Instead, you might prefer to use a std::vector:
std::vector<double> arr(40000);
And simply change the first argument of generateArray to a std::vector<double>&.
You simply give it a pointer, but never allocate any memory for the array. You want a data = new double[count] in your generateArray, or to simply allocate it beforehand with double arr[40000] (or better yet, use a vector).
This would be preferable as:
std::vector<double> generateArray(int count) {
std::vector<double> data(count);
for (int i = 0; i < count; i++)
data[i] = rand() / ((rand() + rand()) / 2.0 + 1);
}
return data;
}
If you need to get array data back somehow, vector is guaranteed to utilize a contiguous array internally, accessible with &v[0] to &v[v.size()-1].
You never initialize the array with a size. You need to do
arr = new double[count];
inside the function. Like below. Don't forget to do delete[] arr; when you're done!
void generateArray(double *data, int count) {
arr = new double[count];
for (int i = 0; i < count; i++)
data[i] = rand() / ((rand() + rand()) / 2.0 + 1);
}
Another option would be doing double *arr = new double[40000] outside the function.

Delete a dynamic array but keep a pointer

I have made a function for expanding array, and this function is inside a class.
Because this function creates new_arr and copies all the numbers of array into the new_arr and at the end sets pointer of array with new_arr, I wold like to know how to delete numbers in array becuse I dont need it any more
void Array::bigger() {
int new_size = size * 2;
int *new_arr = new int[new_size];
for (int f1=0; f1<last; f1++) {
new_arr[f1] = array[f1];
}
this->size = new_size;
array = new_arr;
}
Thanks
Assuming this is an exercise, then delete the array before re-assigning to the new one:
delete [] array;
array = new_arr;
In real code, use an std::vector<int> instead of the dynamically allocated array.
free memory before lose pointer to it:
void Array::bigger() {
int new_size = size * 2;
int *new_arr = new int[new_size];
for (int f1=0; f1<last; f1++) {
new_arr[f1] = array[f1];
}
this->size = new_size;
delete[] array; //free memory
array = new_arr;
}

Copying from One Dynamically Allocated Array to Another C++

This seems like it should have a super easy solution, but I just can't figure it out. I am simply creating a resized array and trying to copy all the original values over, and then finally deleting the old array to free the memory.
void ResizeArray(int *orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
What seems to be happening here is that resized[i] = orig[i] is copying values by reference rather than value, as printing orig after it gets resized returns a bunch of junk values unless I comment out delete [] orig. How can I make a deep copy from orig to resized, or is there some other problem that I am facing? I do not want to use std::vector.
Remember, parameters in C++ are passed by value. You are assigning resized to a copy of the pointer that was passed to you, the pointer outside the function remains the same.
You should either use a double indirection (or a "double pointer", i.e. a pointer to a pointer to int):
void ResizeArray(int **orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = (*orig)[i];
delete [] *orig;
*orig = resized;
}
or a reference to the pointer:
void ResizeArray(int *&orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
By the way, for array sizes you should use the type std::size_t from <cstddef> - it is guaranteed to hold the size for any object and makes clear that we are dealing with the size of an object.
I highly suggest replacing the arrays with std::vector<int>. This data structure will resize as needed and the resizing has already been tested.
orig must be a pointer to a pointer to assign it to resized:
int **orig;
*orig = resized;