Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

2次元配列の動的確保

569 views
Skip to first unread message

TAKE1

unread,
Jul 31, 2001, 11:18:35 AM7/31/01
to
2次元配列の動的確保の方法で困っています。

1行1列、2行2列、、、、n行n列
というように動的に行列を増やす。

配列は別確保しない。(本当に1つの配列をふやしていく)

配列に入れた内容は、初期化しない。


r[1][1],r[2][2].....r[n][n]

ということをしたいのですが、
どのようにすればよいでしょうか。

どうか宜しくお願いいたします。

TAKE1


youka

unread,
Jul 31, 2001, 12:08:37 PM7/31/01
to
 こんばんは、ようかと申します。

>1行1列、2行2列、、、、n行n列
>というように動的に行列を増やす。
>
>配列は別確保しない。(本当に1つの配列をふやしていく)
>
>配列に入れた内容は、初期化しない。
>
>例
>r[1][1],r[2][2].....r[n][n]

 配列の添字は0から始まることをお忘れなく。
 2次元配列の動的確保ならできるのですよね。「配列は別確保しな
い」というのはmalloc()&memcpy()をするなということでしょうか?
 もしそうならrealloc()はどうですか? 場合によってはmalloc()&
memcpy()と同じ動作をするのかもしれませんが(良く知りません)。

#C++なら、vector<>。

--
ようか
mailto:yo...@kun.ne.jp

TAKE1

unread,
Aug 1, 2001, 1:33:04 PM8/1/01
to
pせわになります。

>
> #C++なら、vector<>。

これなら、2次元配列の動的確保+配列に入力した値の保証を
してくれるのでしょうか。

malloc,mallocで2次元配列。realloc,reallocで動的に増やす。
は、考えました。
しかし、配列に入力した値の保証が無いらしいのです。
私も、完全にmallocをマスターしていません。
(ポインタで行き詰まっている。)

今一番困っているのは、mallocやポインタなどを初心者でもわかりやすく
かつ、スキルアップにつながる本が
どれか分からない。
どの本を見ても、わかりにくい、または、説明が少なく内容が浅い。

C++、Cの
おすすめ本は何かありますか。

宜しくお願いいたします。

KATAYAMA Yoshio

unread,
Aug 2, 2001, 12:52:00 AM8/2/01
to
In article <9k9eht$p7t$1...@news.stnet.ad.jp>,
"TAKE1" <take...@mail2.netwave.or.jp> writes:

>malloc,mallocで2次元配列。realloc,reallocで動的に増やす。
>は、考えました。

2次元配列が一つの連続した領域(↓)でなく、

┏━┯━┯━┯   ┓
┠─┼─┼─┼・・・┨
┠─┼─┼─┼   ┨
・・・      
┗━┷━┷━┷   ┛

(1次元配列への)ポインタの配列(↓)でよいなら、

┏━┓
┃ ╂─→┏━┯━┯・・・┓
┠─┨  ┗━┷━┷   ┛
┃ ╂─→┏━┯━┯・・・┓
┠─┨  ┗━┷━┷   ┛
・・・
┗━┛

配列の作成は、

TYPE **
create_array(int n)
{
TYPE **p;
int i;

p = malloc(n * sizeof(TYPE *));
for (i = 0; i < n; i++) {
p[i] = malloc(n * sizeof(TYPE));
}
return p;
}

大きさの変更は、

TYPE **
resize_array(TYPE **array, int old_size, int new_size)
{
int i;

/* 小さくする場合は、不要になった部分を解放 */
for (i = new_size; i < old_size; i++) {
free(array[i]);
}
array = realloc(array, new_size * sizeof(TYPE *));
/* 元の領域の拡張 */
for (i = 0; i < old_size; i++) {
array[i] = realloc(array[i], new_size * sizeof(TYPE));
}
/* 追加する領域 */
for (; i < new_size; i++) {
array[i] = malloc(new_size * sizeof(TYPE));
}
return array;
}

で出来ます。

#簡単のため、エラーチェックは省略しています

>しかし、配列に入力した値の保証が無いらしいのです。

realloc() は元の領域の内容をコピーします。領域が大きくなる場合、
大きくなった部分の内容は不定です。

realloc() が返してくる領域のアドレスは、元の領域と無関係です。元
の領域を指しているポインターは、すべて変更する必要があります。
--
片山@PFU

TAKE1

unread,
Aug 3, 2001, 10:22:31 AM8/3/01
to
お世話になります。


>
> 2次元配列が一つの連続した領域(↓)でなく、
>
> ┏━┯━┯━┯   ┓
> ┠─┼─┼─┼・・・┨
> ┠─┼─┼─┼   ┨
> ・・・      
> ┗━┷━┷━┷   ┛
>
> (1次元配列への)ポインタの配列(↓)でよいなら、
>
> ┏━┓
> ┃ ╂─→┏━┯━┯・・・┓
> ┠─┨  ┗━┷━┷   ┛
> ┃ ╂─→┏━┯━┯・・・┓
> ┠─┨  ┗━┷━┷   ┛
> ・・・
> ┗━┛

上記での違いが分かりませんが
p[ ][ ]で呼び出せるのであれば構わないです。
(ポインタのポインタは、単純に2次元配列とかんがえていたので
深く考えて使っていませんでした。
何か不都合があるのでしょうか?)

>
> realloc() が返してくる領域のアドレスは、元の領域と無関係です。元
> の領域を指しているポインターは、すべて変更する必要があります。

これが問題かと。
これってポインタ名を変えなくてはならないって事でしょうか。

どうか宜しくお願いいたします。

youka

unread,
Aug 3, 2001, 12:51:40 PM8/3/01
to
>> #C++なら、vector<>。
>
>これなら、2次元配列の動的確保+配列に入力した値の保証を
>してくれるのでしょうか。

 1次元配列ならしてくれます。realloc()を使うよりはよっぽど使いや
すいと思います。
 2次元配列はvector<>を組み合わせて実現します。このあたりは
malloc()でするのと同じです。

 vector<>を使うためにC++を、他の部分はCで、というのであれば
realloc()を使って全部Cにした方が良かろうかと思います。

--
ようか
mailto:yo...@kun.ne.jp

youka

unread,
Aug 3, 2001, 12:51:39 PM8/3/01
to
>> 2次元配列が一つの連続した領域(↓)でなく、
>>
>> ┏━┯━┯━┯   ┓
>> ┠─┼─┼─┼・・・┨
>> ┠─┼─┼─┼   ┨
>> ・・・      
>> ┗━┷━┷━┷   ┛
>>
>> (1次元配列への)ポインタの配列(↓)でよいなら、
>>
>> ┏━┓
>> ┃ ╂─→┏━┯━┯・・・┓
>> ┠─┨  ┗━┷━┷   ┛
>> ┃ ╂─→┏━┯━┯・・・┓
>> ┠─┨  ┗━┷━┷   ┛
>> ・・・
>> ┗━┛
>
>上記での違いが分かりませんが
>p[ ][ ]で呼び出せるのであれば構わないです。
>(ポインタのポインタは、単純に2次元配列とかんがえていたので
>深く考えて使っていませんでした。
>何か不都合があるのでしょうか?)

 本物と擬似の違いはありますが使い方は同じなので、領域確保の段階
で問題なければ特に不都合はないと思います(ただし『使うだけ』な
ら。ポインタのポインタと2次元配列の違いはまた別の話かと)。


>> realloc() が返してくる領域のアドレスは、元の領域と無関係です。元
>> の領域を指しているポインターは、すべて変更する必要があります。
>
>これが問題かと。
>これってポインタ名を変えなくてはならないって事でしょうか。

 realloc()を使ってもデータは保存されるので大丈夫です(ただし領域
縮小の時はあぶれた分が捨てられます)。ポインタ名は変える必要はあ
りません。realloc()に渡したポインタは基本的にゴミになっていると
思って良いです。

buf = malloc(50);
buf = realloc(buf, 100);

--
ようか
mailto:yo...@kun.ne.jp

TAKE1

unread,
Aug 5, 2001, 10:26:17 AM8/5/01
to
おせわになります。

>
>  本物と擬似の違いはありますが使い方は同じなので、領域確保の段階
> で問題なければ特に不都合はないと思います(ただし『使うだけ』な
> ら。ポインタのポインタと2次元配列の違いはまた別の話かと)。
>

ポインタのポインタではなくて、mallocのmallocですね。
言いたかったのは。(^^;

いままで、Cでしかプログラムを組んだことがなかったのです。
しかし、C++に変わろうかと思っているのですが、
最初の段階で挫折しそうになっているのです。

(C++は、CたすJAVA割る2みたいな感じに思えるのです。
JAVAも最初の時点で挫折しました。
クラスとか、なんか訳わからん、てな感じで苦しんでおります。)

いままでに、教えていただいた方法で
1度プログラムを組んでみます。

ようかさん、片山さん、ありがとうございました。

やねのすずめ

unread,
Sep 1, 2001, 10:34:31 AM9/1/01
to
忘れた頃にやねのすずめ。(^^ゞ
japan.sci.algorithm にもクロスポストしています。

TAKE1 さんの <9k6i96$r69$1...@news.stnet.ad.jp> より...


>2次元配列の動的確保の方法で困っています。
>
>1行1列、2行2列、、、、n行n列
>というように動的に行列を増やす。
>
>配列は別確保しない。(本当に1つの配列をふやしていく)
>
>配列に入れた内容は、初期化しない。
>
>例
>r[1][1],r[2][2].....r[n][n]
>
>ということをしたいのですが、
>どのようにすればよいでしょうか。


2次元配列 a[y,x] の要素に図のような順序で番号を付けます。

  x 0 1 2 3 4
 y
  +---+---+---+---+---+
 0 | 0| 1| 4| 9| 16| …
  +---+-↓+-↓+-↓+-↓+
 1 | 3← 2| 5| 10| 17|
  +---+---+-↓+-↓+-↓+
 2 | 8← 7← 6| 11| 18|
  +---+---+---+-↓+-↓+
 3 | 15←14←13←12| 19|
  +---+---+---+---+-↓+
 4 | 24←23←22←21←20|
  +---+---+---+---+---+
  :

番号 i は
 x <= y のとき i = ( y + 1 ) * ( y + 1 ) - x - 1
 x >= y のとき i = x * x + y
で計算できますので、1次元配列 b[i] に置き換えれば
明示的にデータをコピーすることなく
C言語の realloc() 関数(メモリ割り当てサイズの変更)で
(擬似)2次元配列 a[y,x] が拡張できます。

x の最大値と y の最大値に差があると無駄な領域が必要ですが…。

--
 (^v^) (.. )(o^< >^o)  ふと思いついて
 (( ))//^ ))(( ))(( ))
= //林 //林 //林 //林 ================================^
  mid...@mtg.biglobe.ne.jp やねのすずめ // \
 http://www5a.biglobe.ne.jp/~espoir/ (ホームページ)//  \

やねのすずめ

unread,
Jan 20, 2006, 11:16:25 AM1/20/06
to
忘れた頃にやねのすずめ。(^^ゞ
# いまさらながら思いついたので、自己フォローです

TAKE1 さんの <9k6i96$r69$1...@news.stnet.ad.jp> より...

>1行1列、2行2列、、、、n行n列
>というように動的に行列を増やす。
>
>配列は別確保しない。(本当に1つの配列をふやしていく)
>
>配列に入れた内容は、初期化しない。
>
>例
>r[1][1],r[2][2].....r[n][n]
>
>ということをしたいのですが、


 添字を付け直し、1次元配列として扱って
C言語の realloc() 関数(メモリ割り当てサイズの変更)を使うのは
同じですが、
x, y を2進法で表して

... x2 x1 x0, ... y2 y1 y0

となるとき、

i = ... y2 x2 y1 x1 y0 x0

を新しい添字とすれば良いですね。
つまり、下図のように番号をつけるわけです:

   0   1   4   5 ...

   2   3   6   7 ...

   8   9  12  13 ...

  10  11  14  15 ...

   :   :   :   :

 この方法は、3次元以上でも応用できます。
また、3進法でも10進法でもできます。

 そのかわり、配列のサイズが 4 (=2^2) のべき乗になったりします。
# 半導体メモリ的

 処理はシフト演算の繰返しでしょう。
# ハードウェア化すると速いかも(線の入れ換えですむので)


--
 (^v^) (.. )(o^< >^o)

 (( ))//^ ))(( ))(( ))
= //林 //林 //林 //林 ================================^

  http://www5a.biglobe.ne.jp/~espoir/ やねのすずめ // \

0 new messages