Meilleure façon de représenter un tableau 2D en C ++ avec une taille déterminée au moment de l'exécution

StackOverflow https://stackoverflow.com/questions/256297

Question

En C ++, j'aimerais faire quelque chose comme:

int n = get_int_from_user();

char* matrix = new char[n][n];

matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';

delete [][] matrix;

mais bien sûr cela ne fonctionne pas. Quelle est la meilleure façon de faire quelque chose de similaire? J'ai déjà vu des solutions à cela, mais elles semblent assez compliquées.

Était-ce utile?

La solution

La méthode dynamique manuelle:

Supposons que vous souhaitiez un tableau de largeur * hauteur, le moyen le plus efficace consiste simplement à utiliser un tableau à une dimension:

char *matrix = new char[width*height];

Pour le supprimer:

delete[] matrix;

Pour y accéder:

char getArrayValue(char *matrix, int row, int col)
{
  return matrix[row + col*width];
}

Pour le modifier:

void setArrayValue(char *matrix, int row, int col, char val)
{
  matrix[row + col*width] = val;
}

Matrice de boost:

Envisagez d'utiliser boost :: matrix si vous pouvez avoir la dépendance.

Vous pouvez ensuite associer le boost linear algèbre bibliothèques.

Voici un exemple de code de renforcement: : matrice :

#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
    for (unsigned j = 0; j < m.size2 (); ++ j)
        m (i, j) = 3 * i + j;

Sur la pile pour certains compilateurs:

Certains compilateurs vous permettent en fait de créer des tableaux sur la pile avec des tailles d’exécution déterminées. g ++ est un exemple d'un tel compilateur. Vous ne pouvez cependant pas faire cela par défaut avec VC ++.

Donc en g ++ c'est un code valide:

int width = 10;
int height = 10; 
int matrix[width][height];

Drew Hall a mentionné que cette fonctionnalité C99 s'appelle VRA (Variable Length Arrays) et qu’elle peut probablement être activée dans n’importe quel compilateur moderne.

Autres conseils

Je fais habituellement quelque chose comme ça:

char *matrix = new char [width * height];

matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';

delete [] matrix;

Qu'en est-il de std::vector< std::vector<int> > array2d;?

Vous semblez manquer l’intérêt du C ++ (C avec les classes) :-). C’est le type d’utilisation qui appelle une classe à l’implémenter.

Vous pourriez simplement utiliser STL ou une autre bibliothèque de classe tierce dont la structure de données, si je ne me trompe pas, aurait la structure que vous recherchiez, mais si vous avez besoin de la vôtre, créez une classe avec les propriétés suivantes.

  • constructeur qui, étant donné n, créera simplement un nouveau tableau n * n de caractères (par exemple, charray) ..
  • fonctions membres qui obtiennent et définissent des valeurs basées sur x.y qui font simplement référence à charray [x * n + y];
  • destructeur qui supprime le tableau [].

Pour un véritable tableau à deux dimensions:

int n = get_int_from_user();

char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
    matrix[i] = new char[n];
}

// Operations on matrix.

for (int i = 0; i < n; i++) {
    delete [] matrix[i];
}
delete matrix;

Juste au dessus de ma tête. Des erreurs sans doute. Cependant, d’autres personnes ont publié une approche plus élégante, je pense.

boost :: multi_array

le faire à la main sera un désordre.

J'aime l'approche en tableau 1-d (la réponse sélectionnée par Brian R. Bondy) avec l'extension selon laquelle vous encapsulez les membres de données dans une classe, de sorte que vous n'ayez pas besoin de garder la trace de la largeur séparément:

class Matrix
{
    int width;
    int height;
    char* data;
public:
    Matrix();
    Matrix(int width, int height);
    ~Matrix();

    char getArrayValue(int row, int col);
    void setArrayValue(int row, int col, char val);
}

La mise en œuvre est un exercice pour le lecteur. ;)

Je pense que ce serait un bon exemple.

int n = get_int_from_user();

char **matrix=new (char*)[n];

for(int i=0;i<n;i++)
    matrix[i]=new char[n];

matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';

for(int i=0;i<n;i++)
    delete []matrix;
delete []matrix;
std::vector<int> m;

Appelez ensuite m.resize () à l'exécution.

int* matrix = new int[w*h];

si vous voulez faire quelque chose comme l'élimination gaussienne, votre matrice devrait être

int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
    matrix[i] = new int[w];

(en élimination gaussienne, nous devons généralement échanger une ligne contre une autre; il est donc préférable d’échanger les pointeurs contre les lignes en temps constant plutôt que de les échanger en les copiant en temps linéaire).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top