Я пытаюсь вернуть элемент данных массива из одного меньшего объекта 2D-массива и пытаюсь вставить массив в более крупный объект 2D-массива. Но пытаясь это сделать, я столкнулся с двумя проблемами.
Первая проблема заключается в том, что я хочу вернуть имя 2D-массива, но я не знаю, как правильно использовать синтаксис для возврата имени 2D-массива.
Так выглядит мой элемент данных 2D-массива
private: int pieceArray[4][4]; // 2D Smaller Array
и я хочу вернуть этот массив в функцию, но это вызывает ошибку компилятора:
int Piece::returnPiece()
{
return pieceArray; //not vaild
// return the 2D array name
}
Я устал использовать этот тип возврата, и он сработал:
int Piece::returnPiece()
{
return pieceArray[4][4];
}
Но я не уверен, что это то, что я хочу, поскольку я хочу вернуть массив и все его содержимое.
Другая проблема - это функция InsertArray (), где я бы поместил функцию returnPiece () в аргумент InsertArray ().
Проблема с InsertArray () - это аргумент, вот код для него:
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];
}
}
}
Проблема в том, что он не принимает мой returnPiece (), и если я удалю «[4] [4]», мой компилятор не примет.
В основном все это синтаксические ошибки, но как мне решить эти проблемы?
Это 3 основные проблемы, с которыми мне нужна помощь, и у меня возникла та же проблема, когда я пытаюсь использовать метод указателя указателя. Кто-нибудь знает, как решить эти 3 проблемы?





Похоже, вам нужно больше узнать об указателях в C++ и о передаче по ссылке или передаче по значению.
Ваш метод returnPiece определяется как возвращающий значение одной ячейки. Учитывая индекс (например, [4] [4]), вы возвращаете копию содержимого этой ячейки, поэтому вы не сможете его изменить, или, вернее, изменение его приведет к изменению копии.
Я уверен, что кто-то предоставит вам правильный синтаксис, но я бы очень рекомендовал изучить этот материал, поскольку в противном случае вы можете использовать код, который вы получили неправильно.
Вот как бы я это сделал:
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];
};
Затем вы можете сделать что-то вроде:
Array x; // create 4x4 array x(1, 2) = 3; // modify element
i и j позиционны, поэтому вы можете использовать любой порядок, который хотите. Было бы неплохо создать конструктор копирования.
Передавая свой массив, вы должны решить, хотите ли вы сделать копию массива или просто хотите вернуть указатель на массив. Для возврата массивов вы не можете (легко) вернуть копию - вы можете вернуть только указатель (или ссылку в C++). Например:
// 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;
}
Чтобы использовать его, назовите его так:
int (*arrayPtr)[4][4] = myPiece->returnPiece();
int cell = (*arrayPtr)[i][j]; // cell now stores the contents of the (i,j)th element
Обратите внимание на сходство между объявлением типа и его использованием - круглые скобки, оператор разыменования * и квадратные скобки находятся в одних и тех же местах.
Ваше объявление для Grid::InsertArray верное - он принимает один аргумент, который представляет собой массив целых чисел 4x4. Это вызов по значению: всякий раз, когда вы вызываете его, вы делаете копию своего массива 4x4, поэтому любые вносимые вами изменения не отражаются в переданном массиве. Если вы вместо этого хотите использовать вызов по ссылке, вы можете вместо этого передайте указатель на массив:
// 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];
}
}
Эти объявления типов с указателями на многомерные массивы могут быстро запутать. Рекомендую сделать для него typedef вот так:
// Declare IntArray4x4Ptr to be a pointer to a 4x4 array of ints
typedef int (*IntArray4x4Ptr)[4][4];
Затем вы можете объявить свои функции более читаемыми:
IntArray4x4Ptr Piece::returnPiece(void) { ... }
void Grid::InsertArray(IntArray4x4Ptr arr) { ... }
Вы также можете использовать программу cdecl, чтобы помочь расшифровать сложные типы C / C++.
Ух ты. Я понятия не имел, что вы можете вернуть 2d-массив. K&R, кажется, не против. Мне пришлось изменить объявление на: int (* returnPiece ()) [4] {return pieceArray; }
Да. если вы хотите, чтобы массив распался, вы можете вернуть "pieceArray" вместо его адреса. будет возвращен указатель на его первый элемент, который имеет тип int (*) [4]. но обратная сторона - вы теряете размер внешнего измерения. я думаю, что подход Адама лучше ...
... если только внешний размер не может иметь произвольный размер. но кажется, что его размер всегда равен 4. Преимущество возврата распавшегося массива заключается в том, что у вас есть естественный синтаксис iindex возвращаемого объекта thingy: foo () [4] [4], а не (* foo ()) [4] [ 4]. Принимая во внимание и то, и другое, я бы все равно предпочел Адама.
Нет, его исходный Grid :: InsertArray (int arr [4] [4]) является вызовом по ссылке. В памяти есть только один массив - pieceArray, и он является общим. Ценности можно менять из-под вас. Для Call-by-Value (копирование) ... Лучший чит со структурой. (Я выложу отдельно.)
Беда с Адама РозенфилдаarrayPtr в том, что Piece :: pieceArray может вылететь из-под вас. (Копирование по ссылке vs Копирование по значению.)
Копирование по значению неэффективно. Но если вы действительно хотите это сделать, просто обманите:
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]
}
Конечно, лучшим, более объектно-ориентированным решением было бы создание returnPiece () и возврат объекта Кусок или Множество. (Как предложил Хуан ...)
общий подход - шаблон <typename T> struct wrap {T t; wrap (T const & t) {memcpy (this-> t, t, sizeof t); }}; шаблон <typename T> wrap <T> make_wrap (T const & t) {return wrap <T> (t); } затем верните make_wrap (pieceArray) и примите wrap <int [4] [4]> в методе InsertArray.
litb: Вы подняли хороший вопрос. Но зачем обобщать кладж для преодоления неспособности C / C++ копировать массивы? make_wrap () не требуется. Остерегайтесь распространять использование memcpy () на типы, содержащие указатели. Учитывая навыки OP с C++, разумно ли увеличивать сложность кодирования с помощью шаблонов?
Более естественно, не следует ли поменять местами i и j? (И, возможно, вместо этого используйте x и y для удобства чтения.) Кроме того, я думаю, что конструктор копирования в порядке ...