I'm trying to code a resizable array, which expands when it's full. All functions are working, but the resize one isn't.
int main(void)
{
int arr[4];
int *ptr = arr;
initializeEmptyArray(ptr);
insertAtIndex(ptr, 0, 4);
insertAtIndex(ptr, 0, 3);
insertAtIndex(ptr, 0, 2);
insertAtIndex(ptr, 0, 1);
resizeArray(&ptr);
for (int i = 0; i < capacity; i )
{
printf("%i", arr[i]);
}
}
This initiates my array [1,2,3,4] and then calls the resize array to test it.
void resizeArray(int **arr)
{
int *newArr = (int *)malloc(capacity * 2 * sizeof(int));
for (int i = 0; i < capacity; i )
{
newArr[i] = (*arr)[i];
}
for (int i = capacity; i < capacity * 2; i )
{
newArr[i] = EMPTY;
}
free(*arr);
*arr = newArr;
}
The problem is the value of arr
when I print it doesn't change to [1,2,3,4,-1,-1,-1,-1] (-1 represents empty). How can I change the pointer to point to this new array?
Capacity stands for the number of elements the array support, initiated as 4 EMPTY is defined as -1, to represent a empty slot in the array.
CodePudding user response:
You can't resize an array. It's size is fixed.
So if you want something that can be resized do:
int arr[4]; --> int* arr = malloc(4 * sizeof *arr);
BTW:
It seems you miss a line like:
capacity = 2 * capacity ;
CodePudding user response:
Hava a look at "realloc", your question sounds like a perfect match
CodePudding user response:
You can not resize an array with automatic storage duration. You can do this with arrays that have allocated storage duration.
So you should remove the array declaration in main and write
int *ptr = malloc( 4 * sizeof( int ) );
or
int *ptr = malloc( capacity * sizeof( int ) );
Also you forgot to change the value of the variable capacity
. I suppose that it is not declared as a constant variable.
In this case the function resizeArray
can look for example the following way
int resizeArray( int **arr )
{
int *newArr = realloc( *arr, capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = capacity; i < capacity * 2; i )
{
newArr[i] = EMPTY;
}
capacity *= 2;
}
return success;
}
Pay attention to that a reallocation of the array can fail. So the function should signal to the caller whether the reallocation was successful.
Also it is not a good idea to use the variable capacity
as a global variable.
You could write in main
int capacity = 4;
int *ptr = malloc( capacity * sizeof( int ) );
// ...
and call the function like
resizeArray( &ptr, &capacity );
In this case the function will look the following way
int resizeArray( int **arr, int *capacity )
{
int *newArr = realloc( *arr, *capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = *capacity; i < *capacity * 2; i )
{
newArr[i] = EMPTY;
}
*capacity *= 2;
}
return success;
}
CodePudding user response:
The two main issues with the code is that arr
is allocated on the stack in main()
, and then you free()
it in resizerArray()
. That is a defect, and I fixed that my heap allocating arr
in main()
instead. In your loop, you print arr[i]
but pass ptr
to resizeArray()
which is updated, but arr
still points to memory that is now free'ed. I fixed this issue by eliminated the ptr
variable:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 0
void resizeArray(int **arr, size_t capacity) {
int *newArr = malloc(2 * capacity * sizeof(int));
// for (int i = 0; i < 2 * capacity; i ) {
// newArr[i] = i < capacity ? (*arr)[i] : EMPTY;
// }
memcpy(newArr, *arr, capacity * sizeof(int));
memset(newArr capacity, EMPTY, capacity * sizeof(int));
free(*arr);
*arr = newArr;
}
int main(void) {
size_t capacity = 4;
int *arr = malloc(capacity * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
for (int i = 0; i < capacity; i ) {
printf("before: %d\n", arr[i]);
}
resizeArray(&arr, capacity);
capacity *= 2;
for (int i = 0; i < capacity; i ) {
printf("after: %d\n", arr[i]);
}
}
I comment out the loop in resizeArray so you can see how you would do that. The code prints:
before: 1
before: 2
before: 3
before: 4
after: 1
after: 2
after: 3
after: 4
after: 0
after: 0
after: 0
after: 0
Both resizeArray()
and the calling code has to know about the factor 2
. This is not a great design. Maybe pass in old and new capacity? Or pass in size_t *capacity
that can be updated if you want to hard-code the factor in resizeArray()
? Remember to check the return value of malloc()
to ensure it did not fail.
See realloc()
for the standard way to resize heap allocated memory, and calloc()
for how to get pre-initialized memory.