1 次元配列を入力として関数を作成しました。main() 部分では、2 次元配列の行をその関数への入力として渡す必要があります。それが可能かどうか、またその方法がわかりません (Matlab では可能ですが、C++ ではわかりません)。なので、どなたか教えていただけるとありがたいです。
3 に答える
関数シグネチャがvoid foo(int a[N])
であり、入力配列が として定義されていると仮定すると、を呼び出しint x[M][N]
てその行を に渡すことができます。ここで、は 2D 配列の行番号を示します。foo
foo(x[i])
i
あなたの関数は次のようになっていると思います。
void function(int row[]) { ... }
最初に理解しておくべき重要なことは、配列型のパラメーターなどは存在しないということです。上記のrow
パラメータは配列のように見えるかもしれませんが、そうではありません。実際、これは。と同等のポインタですint* row
。
次に理解すべきことは、配列の名前を暗黙的に最初の要素へのポインターに変換できることです。配列があるとしましょう。それを関数に渡すためにint array[] = {1, 2, 3, 4, 5};
行うことができます。function(array)
ただし、実際には配列を渡していません。実際に起こっていることは、array
渡される引数が最初の要素へのポインターに変換されているということ1
です。つまり、配列内の値へのポインターです。これまで見てきたように、関数パラメーターrow
は実際にはポインターなので、このポインターを最初の要素に渡すのは問題ありません。
さて、あなたは次のような2次元配列を持っていると思います。
int array[N][M] = { ... };
N
行数と列数を考慮するとM
(どちらの方法でも想像できますが、これはMATLABの知識と一致しています)、array[0][1]
最初の行の2番目の要素にアクセスすることがわかります( C ++の0からのインデックス)。のように1つの添え字を指定するだけの場合array[0]
、これは2次元行列の行全体を表します。その式array[0]
、、はint
sの配列です。このint
sの配列は最初の要素へのポインターに変換できるため、渡すことができ、関数は最初の行(またはth行)の最初の要素へのポインターをarray[0]
として受け取ります。row
0
したがって、次のことができます。
function(array[0]);
ただし、row
は実際にはポインタであるため、関数内では、配列が実際にどのサイズであるかがわかりません。配列のサイズを同時に渡すのが一般的です。
void function(int row[], int size);
function(array[0], M);
ただし、このような配列型を使用することは、一般的に慣用的なC++のベストプラクティスではありません。標準ライブラリが提供するコンテナを使用することをお勧めします。たとえば、astd::array<std::array<int, M>, N>
は適切な固定サイズの2次元配列アナログです。
void function(std::array<int, M> row);
std::array<std::array<int, M>, N> array;
// Fill array...
function(array[0]);
std::array
およびその他の標準コンテナタイプはサイズを取得するためのメカニズムを提供するため、配列のサイズを渡す必要はありません。
列を関数に渡すのは非常に簡単です。
void gimmeColumn(int x[]) {}
int main() {
int table[10][10];
int columnToPass = 3;
gimmeColumn( table[columnToPass] );
}
ただし、同様の方法で行を渡すことはできません。この動作を容易にするために、独自のクラスを作成することを検討できます。
template<type T>
class SelectableTable {
private:
T** table;
int rows, columns;
public:
SelectableTable( int numRows, int numColumns )
:
rows( numRows ),
columns( numColumns )
{
table = new T*[columns];
for( int i=0; i<columns; i++ )
table[i] = new T[rows];
}
~SelectableTable() {
for( int i=0; i<columns; i++ )
delete[] table[i];
delete[] table;
}
T* operator[](int column) {
return table[column];
}
int getRows() {
return rows;
}
int getColumns() {
return columns;
}
TableRow selectRow(int row) {
return TableRow<T>( *this, row );
}
};
template<type T>
class TableRow {
private:
int row;
SelectableTable<T>& table;
public:
TableRow( SelectableTable<T>& fromTable, int selectedRow )
:
table(fromTable),
row(selectedRow)
{}
T& operator[](int column) {
return table[column][row];
}
int size() {
return table.getColumns();
}
};
そして、これを次のように簡単に使用できます。
void gimmeRow( TableRow<int> row ) {
for( int i=1; i<row.size(); i++ )
row[i] = row[i-1];
}
int main() {
SelectableTable<int> table(10,10);
int rowToPass = 3;
gimmeRow( table.selectRow(rowToPass) );
}
もちろん、このコードを機能させるには、ヘッダーを使用するのが最善の方法で、いくつかの前方宣言を追加する必要があります。統一性のために、 class を実装することもできますTableColumn
。