2008-12-31 9 views
2

J'essaie de renvoyer un membre de données de tableau à partir d'un objet de tableau 2D plus petit et d'essayer d'insérer le tableau dans un objet de tableau 2D plus grand. Mais en essayant cela, j'ai rencontré deux problèmes.C++ Retour et insertion d'un objet de tableau 2D

Le premier problème est que je veux retourner le nom du tableau 2D, mais je ne sais pas comment correctement syntaxe pour retourner le nom du tableau 2D.

C'est ce que mon membre de données Array 2D ressemble

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

et je veux retourner ce tableau dans une fonction, mais celui-ci provoque une erreur du compilateur:

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

Je fatigué en utilisant ce type de retour et cela a fonctionné:

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

Mais je ne suis pas sûr si c'est ce que je veux, comme je veux pour retourner le tableau et tout son contenu.

L'autre problème est la fonction InsertArray(), où je mettrais la fonction returnPiece() dans l'argument InsertArray().

Le problème avec le InsertArray() est l'argument, voici le code pour elle:

 
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]; 
     } 
    } 
} 

Le problème est qu'il n'accepte pas mon returnPiece(), et si je supprimer le « [ 4] [4] ", mon compilateur n'accepte pas.

La plupart d'entre eux sont des erreurs de syntaxe, mais comment résoudre ces problèmes?

  1. Revenant l'ensemble pieceArray dans returnPiece()
  2. La syntaxe correcte pour l'argument dans InsertArray()
  3. L'argument de InsertArray() acceptant la returnPiece()

Ces 3 sont Les problèmes majeurs que j'ai besoin d'aide, et ont eu le même problème lorsque je tente d'utiliser la méthode du pointeur de pointeur. Est-ce que quelqu'un sait comment résoudre ces 3 problèmes?

Répondre

3

En passant votre tableau autour, vous devez décider si vous souhaitez ou non faire une copie du tableau, ou si vous voulez simplement renvoyer un pointeur sur le tableau. Pour retourner des tableaux, vous ne pouvez pas (facilement) retourner une copie - vous pouvez seulement retourner un pointeur (ou une référence en C++). Par exemple:

// 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; 
} 

Pour l'utiliser, l'appeler comme ceci:

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

Notez la similitude entre la déclaration de type et de l'utiliser - les parenthèses, opérateur de déréférencement *, et les supports sont dans le même des endroits.

Votre déclaration pour Grid::InsertArray est correcte - elle prend un argument, qui est un tableau 4x4 d'entiers. C'est un appel par valeur: chaque fois que vous l'appelez, vous faites une copie de votre tableau 4x4, donc toute modification que vous faites n'est pas reflétée dans le tableau transmis. Si vous vouliez plutôt utiliser l'appel par référence, vous pourriez passer un pointeur vers un tableau à la place:

// 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]; 
    } 
} 

Ces déclarations de type avec des pointeurs vers des tableaux multidimensionnels peuvent être vraiment déroutant rapide. Je vous recommande de faire un typedef pour elle comme ceci:

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

Ensuite, vous pouvez déclarer vos fonctions beaucoup plus lisible:

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

Vous pouvez également utiliser le programme cdecl pour aider à déchiffrer complexe C/C types ++.

+0

Wow. Je n'avais aucune idée que vous pouviez retourner un tableau 2d. K & R semble être cool avec ça. J'ai dû changer la déclaration à: int (* returnPiece()) [4] { return pieceArray; } –

+0

Oui. Si vous voulez que le tableau se désintègre, vous pouvez retourner "pieceArray" au lieu de son adresse.un pointeur vers son premier élément sera retourné, qui est de type int (*) [4]. mais à la baisse, vous perdez la taille de la dimension extérieure. Je pense que l'approche de adam est mieux ... –

+0

... à moins que la dimension extérieure peut avoir une taille arbitraire. mais il semble être dimensionné pour 4 à l'envers always.an de retourner le tableau cariée est que vous avez la syntaxe iIndex naturelle du thingy retourné: foo() [4] [4] et non (* foo()) [4] [ 4] plus.tout en prenant en considération, je préférerais toujours Adam. –

0

Il semble que vous ayez besoin d'en savoir plus sur les pointeurs en C++ et sur le passage par référence par rapport au passage par valeur.

Votre méthode returnPiece est définie comme renvoyant la valeur d'une seule cellule. Étant donné l'index (par exemple, [4] [4]), vous renvoyez une copie du contenu de cette cellule, vous ne pourrez donc pas le modifier, ou plus exactement, le changer changerait la copie.

Je suis sûr que quelqu'un vous donnera la syntaxe correcte, mais je recommande vraiment d'apprendre ce genre de choses, sinon vous pouvez utiliser le code que vous obtenez incorrectement.

0

Voici comment je le ferais:

 
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]; 
}; 

Vous pouvez faire quelque chose comme:

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

Plus naturellement, ne devrais-je pas permuté entre i et j? (Et peut-être utiliser x et y à la place pour la lisibilité.) Aussi, je pense qu'un constructeur de copie est dans l'ordre ... – strager

+0

i et j sont positionnels, de sorte que vous pouvez utiliser l'ordre que vous voulez. Créer un constructeur de copie serait une bonne idée. –

0

Trouble with Adam de Rosenfield arrayPtr dans cette Piece :: pieceArray peut changer de sous vous. (Copie par référence contre Copie par valeur.)

La copie par valeur est inefficace. Mais si vous voulez vraiment faire, il suffit de tricher:

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] 
} 

Bien sûr, une meilleure, solution plus orientée objet, serait d'avoir returnPiece() créer et retourner une Piece ou tableau objet. (Comme Juan suggéré ...)

+0

une approche générale serait modèle enveloppe struct {T t; enveloppe (T const & t) {memcpy (this-> t, t, taille de t); }}; modèle wrap make_wrap (T const & t) {return wrap (t); } Puis retourner make_wrap (pieceArray) et accepter une pellicule dans la méthode InsertArray. –

+0

litb: Vous soulignez un bon point. Mais pourquoi généraliser un kludge pour surmonter l'incapacité de C/C++ à copier des tableaux? make_wrap() est inutile. Méfiez-vous de généraliser l'utilisation de memcpy() aux types qui incluent des pointeurs. Compte tenu de la compétence d'OP avec C++, augmente la complexité de codage grâce à des modèles sage? –

Questions connexes