Question

I am trying to return an array Data Member from one smaller 2D Array Object, and trying to insert the array into a larger 2D array object. But when attempting this, I came into two problems.

First problem is that I want to return the name of the 2D array, but I do not know how to properly syntax to return 2D Array name.

This is what my 2D Array data member looks like

private:
int pieceArray[4][4];
// 2D Smaller Array

and I want to return this array into a function, but this one causes a compiler error:

int Piece::returnPiece()
{
    return pieceArray; //not vaild
    // return the 2D array name
}

I tired using this return type and it worked:

int Piece::returnPiece()
{
    return pieceArray[4][4];
}

But I am unsure if this is what I want, as I want to return the array and all of it's content.

The other problem is the InsertArray() function, where I would put the returnPiece() function in the InsertArray()'s argument.

The problem with the InsertArray() is the argument, heres the code for it:

void Grid::InsertArray( int arr[4][4] ) //Compiler accepts, but does not work
{
    for(int i = 0; i < x_ROWS ; ++i)
    {
         for (int j = 0; j < y_COLUMNS ; ++j)
         {
             squares[i][j] = arr[i][j];
         }
    }
}

The problem with this is that it does not accept my returnPiece(), and if i remove the "[4][4]", my compiler does not accept.

Mostly all these are syntax errors, but how do I solve these problems?

  1. Returning the whole pieceArray in returnPiece()
  2. The correct syntax for the argument in InsertArray()
  3. The argument of InsertArray() accepting the returnPiece()

These 3 are the major problems that I need help with, and had the same problem when I attempt to use the pointer pointer method. Does anyone know how to solve these 3 problems?

Was it helpful?

Solution

When passing your array around, you have to decide whether or not you want to make a copy of the array, or if you just want to return a pointer to the array. For returning arrays, you can't (easily) return a copy - you can only return a pointer (or reference in C++). For example:

// Piece::returnPiece is a function taking no arguments and returning a pointer to a
// 4x4 array of integers
int (*Piece::returnPiece(void))[4][4]
{
    // return pointer to the array
    return &pieceArray;
}

To use it, call it like so:

int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j];  // cell now stores the contents of the (i,j)th element

Note the similarity between the type declaration and using it - the parentheses, dereferencing operator *, and brackets are in the same places.

Your declaration for Grid::InsertArray is correct - it takes one argument, which is a 4x4 array of integers. This is call-by-value: whenever you call it, you make a copy of your 4x4 array, so any modification you make are not reflected in the array passed in. If you instead wanted to use call-by-reference, you could pass a pointer to an array instead:

// InsertArray takes one argument which is a pointer to a 4x4 array of integers
void Grid::InsertArray(int (*arr)[4][4])
{
     for(int i = 0; i < x_ROWS; i++)
     {
         for(int j = 0; j < y_COLUMNS ; j++)
             squares[i][j] = (*arr)[i][j];
     }
}

These type declarations with pointers to multidimensional arrays can get really confusing fast. I recommend making a typedef for it like so:

// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];

Then you can declare your functions much more readable:

IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }

You can also use the cdecl program to help decipher complicated C/C++ types.

OTHER TIPS

It seems like you need to read up more on pointers in C++ and on pass by reference vs. pass by value.

Your returnPiece method is defined as returning the value of a single cell. Given the index (e.g., [4][4]) you return a copy of the contents of that cell, so you won't be able to change it, or more correctly, changing it would change the copy.

I'm sure someone will give you the correct syntax, but I would really recommend learning this stuff since otherwise you may use the code that you do get incorrectly.

Here is how I would do it:

class Array {
  public:

    Array() {
      for (int i = 0; i < 4; ++i)
      {
         for (int j = 0; j < 4; ++j)
         {
            (*this)(i, j) = 0;
         }
      }
    }


    int &operator()(int i, int j)
    {
      return pieceArray[i][j];
    }

  private:
    int pieceArray[4][4];
};

You can then do something like:

  Array x; // create 4x4 array
  x(1, 2) = 3; // modify element

Trouble with Adam Rosenfield's arrayPtr in that Piece::pieceArray can change out from under you. (Copy-by-reference vs Copy-by-value.)

Copy-by-value is inefficient. But if you really want to do it, just cheat:

struct FOO { int  piece [4][4]; };

FOO Piece::returnPiece()
{
  FOO f;
  memcpy( f.piece, pieceArray, sizeof(pieceArray) );
  return f;
}

void Grid::InsertArray( const FOO & theFoo )
{
  // use theFoo.piece[i][j]
}

Of course, a better, more Object-Oriented solution, would be to have returnPiece() create and return a Piece or Array object. (As Juan suggested...)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top