Deleting 3d Dynamic array in c++ - c++

I made a function to initialize a dynamic 3d array
void initialize_array_3d(char ***Array, int size1, int size2, int size3)
{
Array = new char**[size1];
for (int t=0; t<size1+1; t++)
{
Array[t] = new char *[size2];
for (int r=0; r<size2+1; r++)
{
Array[t][r] = new char [size3];
}
}
}
And it works fine but when I try to delete it with a function
void deinitialize_array_3d(char ***Array, int size1, int size2)
{
for (int t=0; t<size1+1; t++)
{
for (int r=0; r<size2+1; r++)
{
delete[] Array[t][r];
}
delete[] Array[t];
}
delete[] Array;
}
My program crashes, why? and how do i fix it?
In main:
int main()
{
char ***Failed;
initialize_array_3d(Failed, 5, 4, 2);
deinitialize_array_3d(Failed, 5, 4);
Failed = nullptr;
return 0;
}

For starters function initialize_array_3d is wrong. It should look at least the following way
void initialize_array_3d( char ****Array, int size1, int size2, int size3 )
^^^^^^^^^^^^^^
{
*Array = new char**[size1];
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
( *Array )[t] = new char *[size2];
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
( *Array )[t][r] = new char [size3];
}
}
}
That is the first parameter should be passed indirectly using pointer.
A function call might look like
initialize_array_3d( &Failed, 5, 4, 2);
^^^^^^^
Otherwise parameter char ***Array is a local variable of the function and the function deals with a copy of the argument. Any changes of the local variable do not influence on the original argument.
Or you could declare the parameter as reference to the pojnter. For example
void initialize_array_3d( char *** &Array, int size1, int size2, int size3 )
^^^^^^^^^^^^^^
{
Array = new char**[size1];
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
Array[t] = new char *[size2];
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
Array[t][r] = new char [size3];
}
}
}
In this case the function call might look like
initialize_array_3d( Failed, 5, 4, 2);
^^^^^^
As for function deinitialize_array_3d then it should look like
void deinitialize_array_3d(char ***Array, int size1, int size2)
{
for ( int t = 0; t < size1; t++ )
^^^^^^^^^
{
for ( int r = 0; r < size2; r++ )
^^^^^^^^^
{
delete[] Array[t][r];
}
delete[] Array[t];
}
delete[] Array;
}

You are using size1 + 1 to loop through your array instead of size1, but because the array is of size1, you can't access element size1. In the initialization you're getting away with it (it's undefined behavior), but you can't delete memory you don't own, so your program crashes.
Consider using a std::vector instead.

Related

Removing a specified value from array

I'm trying to create a function which will copy elements from one array to another array, unless a specified variable is mentioned, in which case it will not be copied over. The function will then output the new array without the specified variables included.
int *NewArray(int array[], int len, int num){
int *array2 = new int[len];
int temp;
for(int i=0;i<len;i++){
temp = array[i];
if(temp != num){
array2[i]=temp;
}
else{
array2[i] = array[i+1];
}
}
return array2;
}
The problem with your for loop is that it uses only one index to access both the arrays. You need two indices.
Say the item you want to remove is at index 1. After that, you need to make sure that
array2[i] = array[i+1];
Even though you have such a line, that is used only for the matching item. It does not use that logic for subsequent items.
This is what you need:
for(int i=0, j = 0; i<len; ++j ){
if(num == array[j]){
++j;
// Don't increment i, increment j
// to skip the element from array
}
else {
array2[i] = array[j];
// Increment i since it is being assigned a value from array.
++i;
}
}
You could use std::copy_if as below:
int *NewArray(int array[], int &len, int num) {
int *array2 = new int[len];
auto it = std::copy_if(array, array + len, array2,
[&num](int const i){ return i != num; });
len = std::distance(array2, it);
return array2;
}
Live Demo
Using something like std::vector would be beneficial in your case, but seeing as you may have a valid reason for using arrays, you are going about it in a more complex way than is needed. This is definitely more c-esque syntax, but I think it performs what you want it to do without really getting into any STL libraries.
#include <iostream>
#include <cstdlib>
int *NewArray(const int const array1[], const size_t len, const int num, size_t *newlen) {
int *array2 = new int[len];
size_t counter = 0;
for (int i = 0; i < len; i++)
if (array1[i] != num)
array2[counter++] = array1[i];
*newlen = counter;
return array2;
}
int main(int argc, char **argv) {
int arr1[] = { 1, 2, 3, 4, 5, 6, 7};
size_t oldlen = sizeof arr1 / sizeof(int);
size_t newlen;
int *arr2 = NewArray(arr1, sizeof arr1 / sizeof(int), 3, &newlen);
int i;
for (i = 0; i < newlen; ++i)
std::cout << arr2[i] << std::endl;
delete arr2;
system("pause");
}
Here's how I would do it with a vector.
std::vector<int> NewVector(const std::vector<int> const vec1, const int num) {
std::vector<int> vec2 (vec1.size());
auto it = std::copy_if(
vec1.begin(), // where to start
vec1.end(), // where to end
vec2.begin(), // where to insert
[&num](const int i) { return i != num; } // lambda predicate
);
vec2.resize(std::distance(vec2.begin(), it));
return vec2;
}

Unable to understand the pointer mechanism

Why is the program below crashing? I tried debugging the code but couldn't understand; I am suspecting that either the program is wrong or the memory to the passed pointer to display function should have been initialized.
#include <iostream>
using namespace std;
int display( int** intarray )
{
int size = 0;
while( size < 10 )
{
*intarray[size] = size;
size++;
}
return size;
}
int main() {
int* intptrarray;
int arraysize = 0;
arraysize = display( &intptrarray );
for ( int indx = 0; indx < arraysize; indx++ )
{
std::cout << intptrarray[indx] << std::endl;
}
return 0;
}
When a pointer is declared, it doesn't point to any specific memory address. To have it point somewhere, you need to allocate memory to it as follows:
#include <iostream>
using namespace std;
int display( int** intarray, int arraysize )
{
int size = 0;
while( size < arraysize )
{
(*intarray)[size] = size;
size++;
}
return size;
}
int main() {
int arraysize = 10;
int* intptrarray = new int[arraysize];
arraysize = display( &intptrarray, arraysize );
for ( int indx = 0; indx < arraysize; indx++ )
{
std::cout << intptrarray[indx] << std::endl;
}
delete[] intptrarray;
return 0;
}
Whenever you allocate memory, you need to remember to deallocate it yourself (delete for a single variable, delete[] for an array).
*intarray[size] should be (*intarray)[size].
However you have not yet allocated any memory either, so in both cases you are causing undefined behaviour by writing through an uninitialized pointer.
A correct way to write this program is:
void display( std::vector<int> &vec )
{
vec.resize(10);
for ( int i = 0; i < 10; ++i )
vec[i] = i;
}
int main()
{
std::vector<int> vec;
display(vec);
for ( int indx = 0; indx < vec.size(); indx++ )
{
std::cout << vec[indx] << std::endl;
}
}
This can be improved by using std::iota and range-based for-loops if you have a modern compiler.

Getting out of scope error with dynamically allocated array

I am getting an out of scope error in my copy function, when I try to copy the contents of the first array into the DMA one. The try-catch block is required.
#include <iostream>
#include <cstdlib>
using namespace std;
void show( const int a[], unsigned elements );
int * copy( const int a[], unsigned els );
void die(const string & msg);
int main()
{
int arr[4] = {4, 2, 3, 6};
show(arr, 4);
int * newArr = copy(arr, 4);
}
void show( const int a[], unsigned elements )
{
for (int i = 0; i < elements; i++)
cout << a[i] << endl;
}
int * copy( const int a[], unsigned els )
{
try
{
int * newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
void die(const string & msg)
{
cerr << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
If you declare the variable inside the try block then it's only accessible there. You can work around this by moving the declaration outside of the block.
int *newArr;
try
{
newArr = new int[els];
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
for (int i = 0; i < els; i++)
newArr[i] = a[i];
Or by moving the rest of the code inside the try.
try
{
int *newArr = new int[els];
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
catch(const bad_alloc &)
{
die("Alloc Failure");
}
Define new array before the try, otherwise it is only defined inside the try block.
The whole point of exceptions is that you do not need to handle all conceivable errors right at the point where they happen, but rather in places of your choice where you are able to respond to them meaningfully. So be generous with the size of your try blocks:
int * copy(const int a[], unsigned els)
{
try
{
int * newArr = new int[els];
for (int i = 0; i < els; i++)
newArr[i] = a[i];
return newArr;
}
catch (const std::bad_alloc &)
{
die("Alloc Failure");
}
}
You can change your code to
int * copy( const int a[], unsigned els ) {
int * newArr = nullptr;
try {
newArr = new int[els];
}
catch(const bad_alloc &) {
die("Alloc Failure");
}
if(newArr) {
for (int i = 0; i < els; i++)
newArr[i] = a[i];
}
return newArr;
}
to overcome your problem. Just initialize newArr correctly.
I think the problem in your Copy-Function is, that the new Array is a local Variable. When you than return it to the caller, the pointer adresses aren't the right ones.
You might better use two arrays which you pass as Referneces into the copy-function, like this:
int& copy(int& newArray, const int& oldArray) { ... }
Here you get a discription about references in c++ if you don't know what they supposed to be: http://en.wikipedia.org/wiki/Reference_%28C%2B%2B%29

Pass By Reference Multidimensional Array With Unknown Size

How to pass by reference multidimensional array with unknown size in C or C++?
EDIT:
For example, in main function I have:
int main(){
int x, y;
int arr[x][y];
// pass_by_ref(/* passing just arr[][] by reference */);
}
and the function:
void pass_by_ref(/* proper parameter for arr[][] */){
// int size_x_Arr = ???
// int size_y_arr = ???
}
How to implement the commented line?
Simply put, you can't. In C, you can't pass by reference, since C has no references. In C++, you can't pass arrays with unknown size, since C++ doesn't support variable-lenght arrays.
Alternative solutions: in C99, pass a pointer to the variable-length array; in C++, pass a reference to std::vector<std::vector<T>>.
Demonstration for C99:
#include <stdio.h>
void foo(int n, int k, int (*arr)[n][k])
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < k; j++) {
printf("%3d ", (*arr)[i][j]);
}
printf("\n");
}
}
int main(int argc, char *argv[])
{
int a = strtol(argv[1], NULL, 10);
int b = strtol(argv[2], NULL, 10);
int arr[a][b];
int i, j;
for (i = 0; i < a; i++) {
for (j = 0; j < b; j++) {
arr[i][j] = i * j;
}
}
foo(a, b, &arr);
return 0;
}
Demonstration for C++03:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
void foo(std::vector < std::vector < int > > &vec)
{
for (std::vector < std::vector < int > >::iterator i = vec.begin(); i != vec.end(); i++) {
for (std::vector<int>::iterator j = i->begin(); j != i->end(); j++) {
std::cout << *j << " ";
}
std::cout << std::endl;
}
}
int main(int argc, char *argv[])
{
int i = strtol(argv[1], NULL, 10);
int j = strtol(argv[2], NULL, 10);
srand(time(NULL));
std::vector < std::vector < int > > vec;
vec.resize(i);
for (std::vector < std::vector < int > >::iterator it = vec.begin(); it != vec.end(); it++) {
it->resize(j);
for (std::vector<int>::iterator jt = it->begin(); jt != it->end(); jt++) {
*jt = random() % 10;
}
}
foo(vec);
return 0;
}
H2CO3's solution will work for C99 or a C2011 compiler that supports VLAs. For C89 or a C2011 compiler that doesn't support VLAs, or (God forbid) a K&R C compiler, you'd have to do something else.
Assuming you're passing a contiguously allocated array, you can pass a pointer to the first element (&a[0][0]) along with the dimension sizes, and then treat it as a 1-D array, mapping indices like so:
void foo( int *a, size_t rows, size_t cols )
{
size_t i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
a[i * rows + j] = some_value();
}
}
}
int main( void )
{
int arr[10][20];
foo( &arr[0][0], 10, 20 );
...
return 0;
}
This will work for arrays allocated on the stack:
T a[M][N];
and for dynamically allocated arrays of the form:
T (*ap)[N] = malloc( M * sizeof *ap );
since both will have contiguously allocated rows. This will not work (or at least, not be guaranteed to work) for dynamically allocated arrays of the form:
T **ap = malloc( M * sizeof *ap );
if (ap)
{
size_t i;
for (i = 0; i < M; i++)
{
ap[i] = malloc( N * sizeof *ap[i] );
}
}
since it's not guaranteed that all the rows will be allocated contiguously to each other.
This is a sort of comment to the good answer of #John Bode
This will not work (or at least, not be guaranteed to work) for
dynamically allocated arrays of the form:
But this variant will:
T **ap = malloc( M * sizeof *ap );
if (ap) return NULL; ---> some error atention
if (ap)
{
ap[0] = malloc( M * N * sizeof *ap[i] );
if (ap[0]) { free(ap); return NULL;} ---> some error atention
size_t i;
for (i = 1; i < M; i++)
{
ap[i] = ap[0] + i * N;
}
}
After use :
free(ap[0]);
free(ap);
for T being int you call foo exactly als for the array int ap[M][N];
foo( &ap[0][0], M, N);
since you guaranteed that all the rows are allocated contiguously to each other.
This allocation is a litter more efficient.
John Bode's explanation is very good, but there is a little mistake:
it should be
i * cols + j
instead of
i * rows + j
If you really want references, then it's only in C++.
En example of a two-dimensional int array passed by reference
void function_taking_an_array(int**& multi_dim_array);
But the reference doesn't have any advantage, so simply use :
void function_taking_an_array(int** multi_dim_array);
I would advice you to use a container to hold your array.

Changing around arrays

I'm doing a lot of different things with manipulating arrays without vectors, I was wondering if any one could help me with shifting elements in an array and expanding an array while initializing the new space with elements. I feel like I'm very close to completing this code, but I'm hitting a block.
#include <iostream>
using namespace std;
// Function prototypes
int *reverse(int *, int);
int *expand(int *, int);
int *shift(int *, int);
void display(int[], int);
void display2(int[], int);
void display3(int[], int);
int main()
{
int const SIZE = 5;
int myArray [SIZE] = {1, 2, 3, 4, 5};
int myArray2 [SIZE] = {1, 2, 3, 4, 5};
int myArray3 [SIZE] = {1, 2, 3, 4, 5};
int *arraPtr;
int *arraPtr2;
int *arraPtr3;
arraPtr = reverse(myArray, SIZE);
display(myArray, SIZE);
arraPtr2 = expand(myArray2, SIZE);
display2(myArray2, SIZE);
arraPtr3 = shift(myArray3, SIZE);
display3(myArray3, SIZE);
delete [] arraPtr;
delete [] arraPtr2;
delete [] arraPtr3;
return 0;
}
int *reverse(int *arr, int size)
{
int *copyArray;
int posChange;
if( size < 0)
return NULL;
copyArray = new int[size];
for (int index = 0; index < --size; index++)
{
posChange = arr[index];
arr[index] = arr[size];
arr[size] = posChange;
}
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray;
newArray = new int[size * 2];
memcpy( newArray, arr, size * sizeof(int));
for (int index = size; index < (size*2); index++)
newArray[index] = 0;
return newArray;
}
int *shift(int *arr, int size)
{
int *newArray;
newArray = arr;
newArray = new int [size + 1];
for (int index = 5; index > 0; index--)
newArray[index] = newArray[index - 1];
return newArray;
}
void display(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
cout << endl;
}
void display2(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
cout << endl;
}
void display3(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout <<arr[index] << " ";
}
cout << endl;
}
There are only two compile error: int newArray; should be int* newArray; and #include <cstring> is missing (necessary for memcpy())
Also, the line display(myArray, SIZE); was probably meant to be display(arraPtr, SIZE); and likewise display2(myArray2, SIZE); -- otherwise you're only displaying the original arrays, not the results of your function calls.
However, this could benefit from the safer and more generic C++ algorithms, std::copy() and std::reverse_copy() at least:
int *reverse(int *arr, int size)
{
int *copyArray = new int[size];
std::reverse_copy(arr, arr+size, copyArray);
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray = new int[size * 2]();
std::copy(arr, arr+size, newArray);
return newArray;
}
int *shift(int *arr, int size)
{
int* newArray = new int [size + 1]();
std::copy(arr, arr+size, newArray+1);
return newArray;
}
full program: https://ideone.com/RNFiV
This is mostly C code but I'll try to give you some tips on the methods of what you're doing more than the syntax:
In your reverse function, you never actually put anything into the new array. Instead of doing some swapping in the for loop, you can just run through the original loop backwards putting the elements into the new array.
In the expand function it looks like you're trying to do two opposite things, copy the memory from the input array to the new one and then overwrite the new array with all zeros. If you want to copy the memory manually you need to have the loop only go the original array copying its values into the new array (and not go through double the size of the original array or else you'll walk off the end of it!). If you want to use memcpy then get rid of the for loop.
I'm not sure what you want the shift function to do but it pretty much just copies the array now.
I don't know exactly what did you want to accomplish but I think it was something like this:
#include <iostream>
#include <cstring> // Needed to compile on most compilers(memcpy), dunno in yours
using namespace std;
// Function prototypes
int *reverse(int *, int);
int *expand(int *, int);
int *shift(int *, int);
void display(int[], int);
void display2(int[], int);
int main()
{
int const SIZE = 5;
int myArray [SIZE] = {1, 2, 3, 4, 5};
int myArray2 [SIZE] = {1, 2, 3, 4, 5};
int myArray3 [SIZE] = {1, 2, 3, 4, 5};
int *arraPtr;
int *arraPtr2;
arraPtr = reverse(myArray, SIZE);
display(arraPtr, SIZE);
arraPtr2 = expand(myArray2, SIZE);
display2(arraPtr2, SIZE * 2);
delete [] arraPtr;
delete [] arraPtr2;
return 0;
}
int *reverse(int *arr, int size)
{
int *copyArray;
int posChange;
if( size < 0)
return NULL;
copyArray = new int[size];
for (int index = 0; index <= --size; index++)
{
posChange = arr[index];
copyArray[index] = arr[size];
copyArray[size] = posChange;
}
return copyArray;
}
int *expand(int *arr, int size)
{
int *newArray;
newArray = new int[size * 2];
memcpy( newArray, arr, size * sizeof(int));
for (int index = size; index < (size*2); index++)
newArray[index] = 0;
return newArray;
}
int *shift(int *arr, int size)
{
int *newArray;
newArray = new int [size + 1];
memcpy( newArray, arr, size * sizeof(int));
return newArray;
}
void display(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << endl << arr[index] << " ";
}
}
void display2(int arr[], int size)
{
for (int index = 0; index < size; index++)
{
cout << arr[index] << " ";
}
}
As a side note, if you have problems with this kind of stuff you should take a look at any good C resource that talks about pointers and pointer arithmetics, it will come in handy when you have to do low level C++ code.