読者です 読者をやめる 読者になる 読者になる

Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

C言語で2次元配列(文字列)の動的確保

スポンサードリンク

f:id:fa11enprince:20150731131832j:plain
C++版はこちら
C++で2次元配列(文字列)の動的確保 - Gobble up pudding

文字列(char型)を扱っているときに、2次元配列で動的確保したい時があります。
int型など文字でないものは1次元配列で代用できるのですが、
例えば、住所など複数レコード格納したいといった場合、利用します。
下記のようなデータの行数・1行あたりの文字数を調べてから確保したいなんていった時に使うテクニックが2次元配列の動的確保です(今回のサンプルでは行数と1行あたりの文字数を調べるところは書きません)。

北海道でっかいどう1-2-3
東京都ほげほげ1-2-3
神奈川県あふあふ2-3-4
……
沖縄県ちんすこう9-9-9

といったようなのを可変長レコードで管理したいといったときに2次元配列の動的確保が
必要になります。

C言語で2次元配列を動的に割り当てる4つの方法 - FLYING
を参考に3つパターンを示します(int型の2次元配列動的確保は上記URLのほうが詳しいです。)

gccで動作確認しています。
VC++の場合は先頭に

#define _CRT_SECURE_NO_WARNINGS

を書けばコンパイルが通ります(sprintfのかわりにsprintf_sというマイクロソフト独自の関数を使えっておこられるあれを無視するやつです)。
ちなみに、Visual Studioですと拡張子を.cにしてやると自動的にCコンパイラが選ばれるようになっています。
C++でコンパイルしようとするとmallocの戻り値をキャストしてくださいと怒られる可能性があります。

コンパイル

gcc -o test.exe test.c

などとしてやればいいでしょう。
プログラムを楽に各都合上、
SIZEYとSIZEXのサイズを固定でdefineしていますが、
本来は動的に与えられるものと考えてください。
ただし、最後の例だけはSIZEXは固定になります。

マジキチ構造でもいけちゃう方法

char arr[64][8]の配列を作る。つまり1行あたり8文字の64行確保です。
よく参考書にのっているやり方でchar arr[y][x]の領域を確保します。
不連続な領域になってしまうので実用性はあるのか謎です。
ガタガタな構造でメモリ節約なんてことをやろうと思うとこの方法しかありません。
ただガタガタ構造を作るためには1行1行文字数をバラバラに指定してmallocを呼ばなきゃなりません。

とりあえず連続領域で確保する方法

連続領域で確保する場合のやり方です。上の例よりちょっとましな方法ですが…。
これも使うの?と言った感じがします。
このやり方だと1行あたりの文字数が固定で確保することになります。

多分一番使える方法

最後に配列へのポインタを利用する方法です。
文字列の長さが固定ならこれがもっとも実用的だと思われます。
純粋なCを使っているときは結構よく使いました。これも当然連続領域となります。
しかし、配列へのポインタの宣言がきもいです(笑)

補足

VC++でC++でコンパイルしているけどもmalloc使いたい場合はキャストが必要です。
なお、最後の例でのキャストはこうなります。

arr = (char (*)[SIZEX])malloc(sizeof(char) * SIZEY * SIZEX);

と非常にキ○いことになっております。