Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a 3D array from user defined function?

I want to return a 3-dimensional array from a user-defined function into my main function.

Let's consider a simple example for any particular values of a, b and c arrays;

int*** my_function(int a[], int b[], int c[])
{
   for (int i = 0; i < 2; i++)
   {
      for (int j; j < 2; j++)
      {
         for (int k; k < 2; k++)
         {
            array[i][j][k] = a[i] * b[j] * c[k];
         }
      }
   }
   return array
}
like image 574
Pramod Sharma Avatar asked Jul 25 '20 10:07

Pramod Sharma


People also ask

Can a user defined function return array?

Returning Arrays of Different SizesWe can do this by using Application. Caller which gives us a Range object, as long as our function is called from a cell. This range is the range of cells passed into the function. If CallerRows > 1 then a column is being passed into the function.

How do I return a 3D array in C++?

#include <iostream> template<std::size_t M, std::size_t N, std::size_t O> void func(int (&arr3d)[M][N][O]) { // some a, b, c for (std::size_t i = 0; i < M; ++i) { for (std::size_t j = 0; j < N; ++j) { for (std::size_t k = 0; k < O; ++k) { arr3d[i][j][k] = a[k] * b[k] * c[k]; std::cout << arr3d[i][j][k] << " "; // to ...

How is array returned from a function?

Return Array from Functions in C++ C++ does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.


Video Answer


5 Answers

Just a remark: an int *** is not suited to return a 3D array. At most it can be used to return a pointer to an array of pointers to arrays of pointers.

And as raw arrays are not first class elements in C++ language, you cannot return an array from a function in a simple an natural way.

What can be done ?

  1. The C++ simple way:

    Do not use raw arrays but std::array is the size if fixed at compile time, or std::vector if it is not. You can then build (and return vectors of vectors or std::array of std::array. Beware a vector of vectors is like an array of pointers: the data is not required to be contiguous, so it is not equivalent to a 3D array. Here, assuming fixed sizes:

     std::array<std::array<std::array<int, 2>, 2>, 2> my_function(int a[], int b[], int c[])
     {
       std::array<std::array<std::array<int, 2>, 2>, 2> array;
       ...
       return array;
     }
    
  2. A custom container (still modern C++)

    If you need to simulate a 3D contiguous container in C++ and have it to behave like a normal object (that can be returned from a function), you will have to build a custom container and its accessor methods. It is not extremely complex, yet it is far from trivial. If you want to go that way, my advice is to use a (1D) vector as the underlying storage to not be bothered with the copy, move, destruct problem with raw allocated storage.

  3. The C-ish way (with raw arrays).

    Multi-dimensional arrays must have all their dimensions but the last one defined at compile time. Once this is said, you still find the 3 common C storage ways: static storage (can be safely returned, but is not thread safe), allocated storage (thread safe, but caller will be responsable for freeing it), caller provided (the caller is responsable for creating the array and pass it to the callee function. I will show you the 3rd way here

     typedef int (*int3D)[2][2];
    
     int3D my_function(int a[], int b[], int c[], int3D array) {
     {
       for(int i=0; i<2; i++)
       {
         ...
       }
       return array;
     }
    

    Usage:

     int arr[2][2][2];
    
     int3D arr3D = my_function(a, b, c, arr);
     // after the call, arr3D == arr is true
    
like image 200
Serge Ballesta Avatar answered Oct 21 '22 06:10

Serge Ballesta


You can use std::array.

If the sizes are compiled time known, I would suggest having std::array, by which you could get contiguous memory layout.

#include <iostream>
#include <array>
#include <algorithm> // std::generate

// alias for the required array
using Array3D = std::array<std::array<std::array<int, 2>, 2>, 2 >;

Array3D func()
{
   Array3D arr3d;
   std::array<int, 2> a{ 10, 20 }, b{ 10, 20 }, c{ 10, 20 }; // some a, b, c


   // iterate through the arrays to initialize them!
   auto input = 1u;
   for (std::array<std::array<int, 2>, 2> & array2D : arr3d) // or auto& array2D: arr3d
      for (std::array<int, 2> & arr : array2D)                // or auto& arr: array2D
         std::generate(arr.begin(), arr.end(), [&input] { return input++; });

   // for array multimplications!
   for (std::array<std::array<int, 2>, 2> & array2D : arr3d) // or auto& array2D
   {
      for (std::array<int, 2> & arr : array2D)               // or auto& arr
      {
         auto arrIndex = 0u;
         for (int& ele : arr)
         {
            ele = a[arrIndex] * b[arrIndex] * c[arrIndex];
            ++arrIndex;
            std::cout << ele << " "; // to print the element!
         }
      }
   }

   return arr3d; // return the array like this!
}

Alternatively using the templated function (with sizes as non-template parameters), you could even pass the array3d by reference and do the calculations just you shown above!

#include <iostream>

template<std::size_t M, std::size_t N, std::size_t O>
void func(int (&arr3d)[M][N][O])
{
   // some a, b, c

   for (std::size_t i = 0; i < M; ++i)
   {
      for (std::size_t j = 0; j < N; ++j)  
      {
         for (std::size_t k = 0; k < O; ++k)
         {
            arr3d[i][j][k] = a[k] * b[k] * c[k];
            std::cout << arr3d[i][j][k] << " "; // to print the element
         }
         std::cout << "\n";
      }
      std::cout << "\n";
   }
   // do not need to return!
}
like image 3
JeJo Avatar answered Oct 21 '22 04:10

JeJo


A better alternative to using pointers is to use std::vector as that will take care of the details of memory allocation and deallocation.

How to initialize 3D vector?

3D vector is simply a vector containing two other vectors inside it. So, if you want to initialize a 3D vector of size X * Y * Z with a value A. Then it can be done as:

vector<vector<vector<int> > > vec (X,vector<vector<int> >(Y,vector <int>(Z,A)))

How to return it from a function?

You can see how to return it from the below example.

vector<vector<vector<int> > >  sample_function()
{

     //sample code

return vec;
}
like image 2
Ayush Jain Avatar answered Oct 21 '22 06:10

Ayush Jain


As others mentioned, you can use std::array or std::vector but a simple way is to pass the array to your function as a parameter (instead of returning). sth like this:

void your_function(int array[2][2][2], /* other parameters */) {
    // body
}

And use it like this:

int main() {
    int arr[2][2][2];
    your_function(arr, /* other arguments */);
    // now do what you want with arr
}
like image 1
AMIR Avatar answered Oct 21 '22 04:10

AMIR


I have got exactly what you wanted

#include <iostream>
using namespace std;

int** form_2d_array(int l, int b)
{
    int **A = new int *[b];
    for (int i = 0; i < b; i++)
        A[i] = new int[l];
    return A;
}

int*** form_3d_array(int l, int b, int h)
{
    int ***A = new int **[h];
    for (int i = 0; i < h; i++)
        A[i] = form_2d_array(l,b);
    return A;
}

int main()
{
    int ***array;
    int l,b,h;
    l=3;b=5;h=3;
    array=form_3d_array(l,b,h);
    for (int i = 0; i < l; i++)
    {
        for (int j=0; j < b; j++)
        {
            for (int k=0; k < h; k++)
            {
                array[i][j][k] = i+j+k;
            }
        }
    }
    for (int k=0; k < h; k++)
    {
        cout<<"Printing "<<k+1<<"th matrix\n";
        for (int i = 0; i < l; i++)
        {
            for (int j=0; j < b; j++)
            {
                cout<<array[i][j][k]<<" ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    
    return 0;
}

The 2d array function returns a 2d array and 3d array function returns a 3d array.

like image 1
ubaid shaikh Avatar answered Oct 21 '22 06:10

ubaid shaikh