Il modo migliore per rappresentare un array 2D in C ++ con dimensioni determinate in fase di esecuzione

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

Domanda

In C ++ vorrei fare qualcosa del tipo:

int n = get_int_from_user();

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

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

delete [][] matrix;

ma ovviamente questo non funziona. Qual è il modo migliore per fare qualcosa di simile? Ho visto alcune soluzioni a questo, ma sembrano piuttosto confuse.

È stato utile?

Soluzione

Il modo dinamico manuale:

Supponiamo che tu voglia un array di larghezza * altezza, il modo più efficiente è semplicemente usare un array monodimensionale:

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

Per eliminarlo:

delete[] matrix;

Per accedervi:

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

Per modificarlo:

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

Boost Matrix:

Prendi in considerazione l'uso di boost :: matrix se puoi avere la dipendenza.

Potresti quindi collegarti al boost linear algebra librerie.

Ecco alcuni codice di esempio di boost: : matrix :

#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;

In pila per alcuni compilatori:

Alcuni compilatori consentono effettivamente di creare array nello stack con dimensioni determinate dal runtime. g ++ è un esempio di tale compilatore. Tuttavia, non è possibile farlo per impostazione predefinita VC ++.

Quindi in g ++ questo è un codice valido:

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

Drew Hall ha menzionato che questa funzione C99 è chiamata Array a lunghezza variabile (VLA) e può probabilmente essere attivata in qualsiasi compilatore moderno.

Altri suggerimenti

Di solito faccio qualcosa del genere:

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

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

delete [] matrix;

Che dire di std :: vector < std :: vector < int > & Gt; array2d; ?

Sembra che manchi l'intero punto del C ++ (C con le classi) :-). Questo è il tipo di utilizzo che chiede a una classe di implementarlo.

potresti semplicemente usare STL o un'altra libreria di classi di terze parti che sono sicuro che avrebbe la struttura di dati che stai cercando, ma, se hai bisogno di creare il tuo, crea una classe con le seguenti proprietà.

  • costruttore che, dato n, creerà semplicemente un nuovo n * n array di caratteri (ad esempio, charray) ..
  • funzioni membro che ottengono e impostano valori basati su x.y che si riferiscono semplicemente a charray [x * n + y];
  • distruttore che elimina [] è l'array.

Per un vero array bidimensionale:

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;

Appena al di sopra della mia testa. Errori, senza dubbio. Tuttavia, altre persone hanno pubblicato un approccio più elegante, credo.

boost :: multi_array

farlo a mano sarà un casino.

Mi piace l'approccio 1-d array (la risposta selezionata da Brian R. Bondy) con l'estensione che avvolge i membri dei dati in una classe in modo da non dover tenere traccia della larghezza separatamente:

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

L'implementazione è un esercizio per il lettore. ;)

Penso che sarebbe una buona idea.

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;

Quindi chiama m.resize () in fase di esecuzione.

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

se vuoi fare qualcosa come l'eliminazione gaussiana la tua matrice dovrebbe essere

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

(nell'eliminazione gaussiana di solito è necessario scambiare una riga con un'altra, quindi è meglio scambiare i puntatori alle righe in tempo costante piuttosto che scambiare copiando in tempo lineare).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top