実行時に決定されたサイズでC ++の2次元配列を表す最良の方法
-
05-07-2019 - |
質問
C ++では、次のようなことをしたいです。
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
もちろん、これは機能しません。同様のことをする最良の方法は何ですか?これに対するいくつかの解決策を見てきましたが、それらはかなり厄介に見えます。
解決
手動の動的な方法:
width * heightの配列が必要だとしましょう。最も効率的な方法は、1次元配列を使用することです:
char *matrix = new char[width*height];
削除するには:
delete[] matrix;
アクセスするには:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
変更するには:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
ブーストマトリックス:
boost :: matrixの使用を検討依存関係を持つことができる場合。
その後、 boost linearに結び付けることができます。代数ライブラリ。
いくつかのブーストのサンプルコード: :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;
一部のコンパイラのスタック:
一部のコンパイラでは、実行時に決定されたサイズでスタック上に配列を作成できます。 g ++はそのようなコンパイラの例です。ただし、デフォルトでVC ++でこれを行うことはできません。
したがって、g ++ではこれは有効なコードです:
int width = 10;
int height = 10;
int matrix[width][height];
ドリューホールは、このC99機能は可変長配列(VLA)と呼ばれ、現代のコンパイラーでおそらくオンにできると述べました。
他のヒント
私は通常、次のようなことをしています:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
std::vector< std::vector<int> > array2d;
はどうですか?
C ++(C with classes)の要点が欠けているようです:-)。これは、クラスがそれを実装することを求めている一種の使用です。
あなたはあなたが探しているデータ構造を持っていると確信しているSTLまたは他のサードパーティのクラスライブラリを使用するだけでできますが、もしあなたが自分でロールする必要があるなら、クラスを作成するだけです次のプロパティを使用します。
- nを指定すると、char(charcharなど)の新しいn * n配列を作成するだけのコンストラクタ。
- 単にcharray [x * n + y]を参照するx.yに基づいて値を取得および設定するメンバー関数
- 配列を削除するデストラクタ[]。
真の2次元配列の場合:
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;
頭のてっぺんから。間違い、間違いありません。しかし、他の人がよりエレガントなアプローチを投稿していると思います。
手作業で行うのは面倒です。
幅を個別に追跡する必要がないように、データメンバーをクラスにラップする拡張機能を備えた1次元配列アプローチ(Brian R. Bondyによる選択された回答)が好きです:
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);
}
実装は読者向けの演習です。 ;)
これは良いものになると思います。
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;
次に、実行時にm.resize()を呼び出します。
int* matrix = new int[w*h];
ガウス消去法のような何かをしたい場合は、行列をすべきです
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(ガウス消去法では通常、行を別の行と交換する必要があるため、線形時間でコピーしてスワップするのではなく、一定の時間で行へのポインターをスワップする方が良いです。)