ここから本文です

C++ プログラミング C++で二次元配列を一次元配列に変換する方法,一次元配列を二...

the********さん

2019/9/1822:57:50

C++ プログラミング
C++で二次元配列を一次元配列に変換する方法,一次元配列を二次元配列に変換する方法とその例のコードを教えてください.

閲覧数:
74
回答数:
3
お礼:
50枚

違反報告

ベストアンサーに選ばれた回答

2019/9/1910:31:01

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q142136608...
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q122137305...
の続きですか?

C++ で二次元配列を一次元配列に変換する汎用的な方法はありません。
例えば
int a[10][20];
であるとき、
int *p = a[0];
とすれば
p で一次元配列のようにアクセス出来ますが、過去の質問を見る限りその手法はとれないようなので、個々にコピーするなりしないとダメじゃないでしょうか?

どのように変換するかが明確じゃないとプログラムを組みようがないですね。

int a[4][3] = {
{ 11, 12, 13 },
{ 21, 22, 23 },
{ 31, 32, 33 },
{ 41, 42, 43 },
};
である場合、
int b[12];
にどのように変換するのでしょうか?
それが決まっていれば、自ずとプログラムも書けるのではないでしょうか。

この回答は投票によってベストアンサーに選ばれました!

ベストアンサー以外の回答

1〜2件/2件中

並び替え:回答日時の
新しい順
|古い順

nyosさん

編集あり2019/9/1916:14:05

こんな感じの型定義とキャスト用の関数があれば可能です。
大元が1次元である必要があります。

//3Dグラフィクス頂点用double 定義
typedef double DoubleV[3];

//飛び幅変換キャスト用テンプレート関数
template<typename vectype,typename valtype>static inline vectype *vector_cast(valtype *vec_top){return (vectype*) vec_top;}


//使用方法
double array[12];

DoubleV *array3d = vector_cast<DoubleV,double >(array);


//各アクセスは以下のように…
array3d[0][0]
array3d[0][1]
array3d[0][2]
array3d[1][0]


array3d[3][2]


std::vector <double>に対しても、変数名vecと仮定して&vec[0]として、先頭アドレスを与えてやれば2次元参照が出来ます。
でもpush_backは一つづつ行う必要はあります。resizeしておいて変換後2次元で入力する方法もありますね。
配列終端のセグメントが合うようにする必要はあります。まあはみ出ててもアクセスしなければ良いですが。
上の例だとDoubleVが配列3つ分なので、元配列は3の倍数にする必要があるので12になってます。


単純に平たいdouble配列を、配列へのポインタキャストして一つ目のポインタでdouble 3つ分の飛び幅にしているだけです。
1次元の配列はスタック上でもヒープ上でもstd::vectorだろうと普通の配列だろうとメモリの連続性が保証されているものであれば、この方法はどんな環境でも有効です。
ただし、飛び幅は固定です。
飛ばした先でさらにvector_castし直せば擬似的に不定形でのアクセスは出来ますが、ちょっとわかりにくくなるのでオススメしません。

テンプレート関数なのでいろんな型に対して使用できます。

2次元から1次元はメモリ領域が連続していない場合は無理です。
これを使うなら、初めから全て1次元配列で生成して、必要な時にvector_castで2次元配列参照できるポインタに変換する方法が処理コストとしても良いです。

効能としては、上の例ですと、3次元頂点配列をリニアアクセスする時に、*3のコストが消えますので、実質繰り返し処理が早くなります。

VSのデバッガなどで変換後配列の第二配列を直接みると第一配列のものに見えるが、ちゃんとアクセスできるので心配御無用


と、聞きたかったのはこういう事でしょうか?

プロフィール画像

カテゴリマスター

あみやさん

2019/9/1910:27:01

//2次配列を宣言
int a[2][2]={{0,1},{2,3}};
//1次ポインタにキャスト
int *b=(int *)a;
//1次配列としてアクセス
for(int i=0; i<4; i++)
cout << i << ":" << b[i] << endl;
とか。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる