多次元配列の動的なメモリ確保の方法

[戻る]
Puppy 2002/05/16(木) 13:48:03
Puppyです。 お世話になっています。

タイトルのとおりの質問なのですけど、例えば1日分のデータが

double dayData1[24][5][10];
double dayData2[24][5];      // のようにあった場合に

今日が24日だった場合に1日から23日分の上記の配列分だけメモリを
確保して、そのメモリに2次元配列および3次元配列でアクセスしたいです。
new の動的確保は多次元配列をサポートしていないようなので、どうしていいか
さっぱりわかりません。

このようなケースでは、皆様はどのように対処されていますか?
いつも聞いてばかりですみません。よろしくお願いしますぅ。 m(..)m ペコリ

2002/05/16(木) 14:06:04
double** dayData2 = new double* [24];

for(int i = 0; i < 24; i++)
  dauData2[i] = new double[5];
.
.
.

for(i = 0; i < 24; i++)
  delete [] dayData2[i];
delete [] dayData2;

って感じですかね
Cでいうところのmalloc/calooc
と同じ感じでできますよ〜

PAI 2002/05/16(木) 14:15:14
私の場合そういうクラスを作って、
std::vector<>
で管理するかな?

dairygoods 2002/05/16(木) 14:48:13
24×5個分のdoubleのメモリを確保して、
2次元配列ポインタにキャストして使用します。
  double (*dayData2)[5] = (double(*)[5])new double[24*5];
  dayData2[x][y] = 100;

2次元配列ポインタで混乱する場合は、1次元のままでも扱えます。
  double *dayData2 = new double[24*5];
  dayData2[x*5+y] = 100;

みみみ 2002/05/16(木) 15:27:59
キャスト必要ないと思います。
size_t days = 24;
double (* data1)[5][10] = new double[days][5][10];
double (* data2)[5] = new double[days][5];
    
delete[] data1;
delete[] data2;

私も二次元以降が可変になる場合は素直に
std::vector<>をつかいます。

Puppy 2002/05/16(木) 17:14:20
Puppyです。 皆様、お返事ありがとうございます。

std::vector というのを使ったことがなかったので、試してみました。
3次元配列で実験したら

「error C2109: 配列または、ポインタでない変数に添字が使われました。」
というエラーが出てしまいます。
どうしたら良いかご存知のかた、教えて下さい。 m(..)m ペコリ

void CTestDlg::MemoryKeep()
{
    int i, j, k;

    vector<vector<int> > IntAry;

    // 3 x 5 x 10

    IntAry.assign(3);

    TRACE("%d\n", IntAry.size());
    for (i = 0; i < IntAry.size(); i++)
        IntAry[i].assign(5);

    TRACE("%d\n", IntAry.size());
    for (j = 0; j < IntAry.size(); i++)
        IntAry[i].assign(10);        // ここが怪しいのかな?

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 5; j++) {
            for (k = 0; k < 10; k++) {
                cout << IntAry[i][j][k] << " ";
            }
        }
    }
}

あと、std::vector はメモリの解放とかは必要ないのでしょうか?

----------------------------------------------------------

配列についても勉強中です。
2次元の場合は以前に YuOさんに下記の通りに教わりました。

int ary[5][10]; // の場合

 ary        int [5][10]型
&ary        int (*)[5][10]型
 ary[0]     int [10]型
&ary[0]     int (*)[10]型
 ary[0][0]  int型
&ary[0][0]  int * 型

int ary[3][5][10]; // の場合
はどうなるのか知りたいです。ぜひ教えて下さい。

いっぱい質問してごめんなさい。よろしくお願いしますぅ。 m(..)m ペコリ

dairygoods 2002/05/16(木) 17:27:01
>    vector<vector<int> > IntAry;
3次元だったら, vector<vector<vector<int> > > では?

Puppy 2002/05/16(木) 17:48:03
dairygoods さん お返事ありがとうございます。

> 3次元だったら, vector<vector<vector<int> > > では?

下記のように試しましたが、うまくいきません。(涙)
どなたか、よろしくお願いします。

{
    int i, j, k;

    vector<vector<vector <int> > >IntAry;

    // 3 x 5 x 10

    IntAry.assign(3);
    for (i = 0; i < 3; i++) {
        IntAry[i].assign(5);
        for (j = 0; j < 5; j++)
            IntAry[i][j].assign(10);
    }
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 5; j++) {
            for (k = 0; k < 10; k++) {
                cout << IntAry[i][j][k] << " ";
            }
        }
    }
}

たいちう 2002/05/16(木) 17:50:06
2次元の場合の私の回答で混乱させてしまったかもしれませんが、
懲りずにまた回答します。

int ary[3][5][10]; // の場合

 ary          int [3][5][10]型
&ary          int (*)[3][5][10]型
 ary[0]       int [5][10]型
&ary[0]       int (*)[5][10]型
 ary[0][0]    int [10]型
&ary[0][0]    int (*)[10]型
 ary[0][0][0] int型
&ary[0][0][0] int*型

多分あっているでしょう。ちなみに、
VCでは下記のコードをコンパイルしようとすると
(エラーメッセージで)確認できます。

int i, ary[3][5][10];
i =  ary;
i = &ary;
i =  ary[0];
i = &ary[0];
i =  ary[0][0];
i = &ary[0][0];
i =  ary[0][0][0];
i = &ary[0][0][0];

Puppy 2002/05/16(木) 17:55:03
たいちうさん お返事ありがとうございます。

参考にして、お勉強します。感謝ですぅ。(^-^;

Puppy 2002/05/16(木) 19:07:46
[[解決]]
下記のコードでできました! ありがとうございました。

warning C4786が出ていたので、てっきりおかしいと思ったら
VCの不具合みたいですね。
下記のコードに何か問題があるようでしたら、教えて下さい。

int i, j, k;

vector<vector<vector <int> > >IntAry;

// 3 x 5 x 10

IntAry.assign(3);
for (i = 0; i < 3; i++) {
    IntAry[i].assign(5);
    for (j = 0; j < 5; j++)
        IntAry[i][j].assign(10);
}
for (i = 0; i < 3; i++) {
    for (j = 0; j < 5; j++) {
        for (k = 0; k < 10; k++) {
            IntAry[i][j][k] = i + j + k;
            TRACE("%d %d %d\n", i, j, k);
        }
    }
}

PAI 2002/05/16(木) 19:43:44
問題はないですけどサイズ変更はこんなかんじでOKですよ。

    using std::vector;
    vector< vector< vector<int> > > a;
    
    // 5-5-10
    a.resize( 5, vector<vector<int> >(5 , vector<int>(10)));
    
    // 3-7-5
    a.clear();
    a.resize( 3, vector<vector<int> >(7 , vector<int>(5)));

あと、ループは
    for(i = 0; i<a.size() ; i++){
        for( j= 0; j<a[i].size(); j++){
            for(k=0; k<a[i][j].size(); k++){
                
                a[i][j][k] = i+j+k;
                cout << i << " " << j << " " << k << endl;
            }
        }
    }
こんな感じがよいかと。


それと、この場合 3-5-10 24-5-10
って感じになってるけど、その n-5-10 の 5-10 の部分は固定?
固定だったら、そういうクラスを作って、それのvectorにするのがよいかと。

>あと、std::vector はメモリの解放とかは必要ないのでしょうか?
いらねぇッス。デストラクタで開放してくれるッス。

dairygoods 2002/05/16(木) 20:37:39
> warning C4786が出ていたので、てっきりおかしいと思ったら
> VCの不具合みたいですね。

これは不具合ではなく仕様です(^^;

C4786のヘルプより:
| 識別子の文字列の長さが制限値を超えたので、
| 切り捨てられました。
| デバッガは、255 文字より長いシンボルを持つ
| コードをデバッグできません。デバッガでは、
| 切り詰められたシンボルの表示、評価、変更、
| およびウォッチはできません。

うっとうしい時は、
#pragma warning(disable: 4786) 
でこの警告を表示しないようにできます。

古いスレッドには追加発言できません。