How to Resize Array in C++

Resizing an array in C

No, you can't change the size of an array. You could use a dynamically allocated list of char* instead and realloc() as required:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main()
{
char** array = malloc(1 * sizeof(*array));

if (array)
{
array[0] = "This";

printf("%s\n------\n", array[0]);

char** tmp = realloc(array, 2 * sizeof(*array));
if (tmp)
{
array = tmp;
array[1] = "That";

printf("%s\n", array[0]);
printf("%s\n", array[1]);
}

free(array);
}
return 0;
}

See online demo: https://ideone.com/ng00k.

Resizing an array with C

Start off by creating the array:

structName ** sarray = (structName **) malloc(0 * sizeof(structName *));

Always keep track of the size separately:

size_t sarray_len = 0;

To increase or truncate:

sarray = (structName **) realloc(sarray, (sarray_len + offset) * sizeof(structName *));

Then set the size:

sarray_len += offset;

Happy to help and hope that helps.

Resizing 2D Arrays in C

Assuming you declared array as

int **array;

and allocated as

array = malloc( sizeof *array * ROWS );
if ( array )
{
for ( size_t i = 0; i < ROWS; i++ )
array[i] = malloc( sizeof *array[i] * COLS );
}

The structure you wind up with looks something like:

       +---+        +---+                  +---+
array: | | -----> | | array[0] ------> | | array[0][0]
+---+ +---+ +---+
... | | array[1] ---+ | | array[0][1]
+---+ | +---+
... | | | array[0][2]
| +---+
| ...
|
| +---+
+--> | | array[1][0]
+---+
| | array[1][1]
+---+
| | array[1][2]
+---+
...

If you want to increase the number of rows in the array but leave the column sizes the same, you'd do something like

int **tmp = realloc( array, sizeof *array * (ROWS + add_rows) );
if ( tmp )
{
array = tmp;
for ( size_t i = 0; i < add_rows; i++ )
{
array[ROWS + i] = malloc( sizeof *array[ROWS + i] * COLS );
}
}

If you want to leave the number of rows the same but increase the number of columns in each row, you would do something like

for ( size_t i = 0; i < ROWS; i++ )
{
int *tmp = realloc( array[i], sizeof *array[i] * (COLS + add_cols) );
if ( tmp )
{
array[i] = tmp;
}
}

If you want to reduce the number of rows in the array, you will need to free the affected rows first:

for ( size_t i = 1; i <= del_rows; i++ )
free( array[ROWS - i] );

int *tmp = realloc( array, ROWS - del_rows );
if ( tmp )
array = tmp;

If you want to reduce the number of columns:

for ( size_t i = 0; i < ROWS: i++ )
{
int *tmp = realloc( array[i], sizeof *array[i] * (COLS - del_cols) );
if ( tmp )
array[i] = tmp;
}

From there, you should be able to figure out any combinations you need. I strongly recommend doing only one dimension at a time (that is, if you want to increase the number of rows and columns, do the rows first, then do the columns).

You always want to assign the result of realloc to a temporary variable; if realloc cannot satisfy the request, it will return NULL, and if you assign it back to the original variable, you will lose your only reference to the memory that was previously allocated, leading to a memory leak.

Manually resize array in C++

The simple answer is you should always use std::vector in this case. However it might be useful to explain just why that is. So lets consider how you would implement this without std::vector so you might see just why you would want to use std::vector:

// Naive approach
Line::push(const Point& p)
{
Point* new_points = new Points[index + 1];
std::copy(std::make_move_iterator(points), std::make_move_iterator(points+index), new_points);
new_points[index] = p;
delete[] points;
points = new_points;
index += 1;
}

This approach has many problems. We are forced to reallocate and move the entire array every time an entry is inserted. However a vector will pre-allocate a reserve and use space out of the reserve for each insert, only re-allocating space once the reserve limit is surpassed. This mean vector will far out perform your code in terms of performance as less time will be spent allocating and moving data unnecessarily. Next is the issue of exceptions, this implementation has no exception guarantees, where as the std::vector provides you with a strong exception guarantee: https://en.wikipedia.org/wiki/Exception_safety. Implementing a strong exception guarantee for your class is none trivial, however you would have automatically got this had you implemented this in terms of std::vector as such

Line::push(const Point& p)
{
points.push_back(p);
}

There are also other more subtle problems with your approach, your class does not define copy or assignment operators and so gets compiler generated shallow copy versions generated which means if someone copies your class then allocated members will get deleted twice. To resolve this you need to follow the rule of 3 paradigm pre C++11 and the rule of 5 for C++ 11 onwards: https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming). However had you used a vector none of this would be needed as you would benefit from the rule of zero and be able to rely on the compiler generated defaults: https://blog.rmf.io/cxx11/rule-of-zero

How to resize array in C++?

The size of an array is static in C++. You cannot dynamically resize it. That's what std::vector is for:

std::vector<int> v; // size of the vector starts at 0

v.push_back(10); // v now has 1 element
v.push_back(20); // v now has 2 elements
v.push_back(30); // v now has 3 elements

v.pop_back(); // removes the 30 and resizes v to 2

v.resize(v.size() - 1); // resizes v to 1

Resizing a two dimensional array in C. Memory leak

If the newsize is smaller, the elements from newsize to size must be freed.

Then the array can be reallocated.

If newsize is larger, the elements from size to newsize need to be set to NULL.

Then reallocate from element 0 to newsize.

For a pointer to pointer the pointer can be returned and assigned. The other option is to pass a pointer to the pointer int ***array.

#include <stdio.h>
#include <stdlib.h>

int **resize ( int **array, int *newsize, int size){
int **temp = NULL;

if ( *newsize < size) {
for ( int i = *newsize; i < size; i++) {
printf ( "free[%d]\n", i);
free ( array[i]);
}
}

if ( NULL == ( temp = realloc ( array, *newsize * sizeof *array))) {
if ( 0 != *newsize) {
fprintf ( stderr, "realloc problem\n");
*newsize = size;
return array;
}
else {
return NULL;
}
}
array = temp;

for ( int i = size; i < *newsize; i++) {
array[i] = NULL;
}

for ( int i = 0; i < *newsize; i++) {
array[i] = realloc ( array[i], *newsize * sizeof **array);
}
printf("\n");
for ( int i = 0; i < *newsize; i++) {
for ( int j = 0; j < *newsize; j++) {
printf ( "[%d][%d]: %p\n", i, j, (void *)&array[i][j]);
}
}
return array;
}

int main ( void) {
char line[6] = "";
int **items = NULL;
int elements = 0;
int oldsize = 0;

printf ( "enter a number\n");
while ( fgets ( line, sizeof line, stdin)) {
if ( 1 == sscanf ( line, "%d", &elements)) {
if ( 0 <= elements) {
items = resize ( items, &elements, oldsize);
oldsize = elements;
}
if ( 0 == elements) {
free ( items);
break;
}
}
else {
printf ( "enter a number\n");
}
}

return 0;
}


Related Topics



Leave a reply



Submit