アプリ版:「スタンプのみでお礼する」機能のリリースについて

ヘッダーファイルから二次元配列を取り込みたいのですが、上手く取り込めません。うまく取り込む方法を詳しく教えて下さい。お願いします。

A 回答 (3件)

 そもそも「ヘッダファイルから二次元配列を読み込む」という発想自体がよくないですね。


 Fookyさんも言われている通り、通常ヘッダファイルに定義は書きません。(C++では例外も多々ありますが)

 恐らくメインとなるソース以外の場所にあるマスターデータを、メインソースから使う方法を知りたいのでしょうが、マスターデータそのものを参照して使うのか、ローカル変数にコピーして使うのかということがはっきりしません。
 Fookyさんは前者を前提に回答されているので、私は後者を前提に回答させていただきます。

・どちらの場合にせよ、データ及び関数の定義はソースファイルに書きます。
 この場合、他のソースからも参照できるようにするための宣言をした、ヘッダファイルも必要になります。
・またマスターデータを、毎回ローカルな二次元配列として初期化するのはムダが多いので、グローバル宣言をして初期化します。
・マスターからデータを取得する関数ですが、Cでは配列を返すことはできないので、配列のポインタを渡し、値をセットするように実装します。
・二次元配列を引数に取る場合、ムリにポインタ表現しなくても、配列表現が許されているので、そのように書きましょう(ROW側は指定してもしなくても無視されます)。

/* data.h */
#define ROW 10
#define COL 10

void init_nijigen(char [ROW][COL]);

/* data.c */
#include <string.h>
#include "data.h"

static const char master[ROW][COL] = {
  {・・・},
    :
};

void init_nijigen(char p[ROW][COL])
{
  memcpy(p, master, ROW * COL);
}

/* main.c */
#include <stdio.h>
#include "data.h"

int main(void)
{
  int ir, ic;
  char nijigenn2[ROW][COL];

  init_nijigen(nijigenn2);

  for (ir = 0; ir < ROW; ir++) {
    for (ic = 0; ic < COL; ic++)
      printf("%c", nijigenn2[ir][ic]);
    putchar('\n');
  }

  return 0;
}

※補足ですが、Fookyさんのソースは、file.cをfile.cppに変えないと、通常の環境ではコンパイルエラーになります。
(Cでは、配列のサイズ指定には定数しか指定できません。const変数が許されるのはC++の言語仕様です。)
    • good
    • 0

確かにCで2次元配列を扱うのは少し難しいんですが、それ以前に色々と問題


があるコードですね。

1.関数file()の戻り値がvoidになっている
 これは2次元配列を返す関数のつもりで書かれているんではないんでしょう
か?それならば、void(戻り値なし)ではなく、2次元配列に相当するものを
返すように宣言しなければなりません。関数の戻り値の指定(void)とreturnの
中に書く変数の型は当然ながら一致していないといけません。

2.それじゃ、2次元配列をどうやって返すのか?
 ここが難しいところなんですが、Cでは配列を一つのモノ(オブジェクト)
として扱うという考え方はしません。RAMの中で配列が格納されているメモ
リの場所(アドレス)を受け渡しします。この、アドレスを入れる変数をポイ
ンタと言います。したがって、file()関数は、10×10配列が格納されてい
るアドレスを指すポインタを返す関数にしないといけません。こんな説明を書
き出すと切りがないので、答え(と言ってもまだまだ間違えています)を書く
と、

char (*file())[10]
{
char nijigen[10][10] = {
{'#','#','#',...,'#'},
....,
{'#','#','#',...,'#'}};

return(nijigen);
}

配列を指すポインタ変数とそれを返す関数の書き方は、

char (*変数名)[10]:「10個のchar型が格納されているメモリを指すポインタ」
          型の変数。
char (*関数名(関数の引数))[10]:「10個のchar…ポインタ」型を返す関数

となります。

3.file()の戻り値を受けるポインタ変数の宣言
 nijigenの宣言は合ってましたが、char nijigen2[10][10];は間違いです。
こう書くと、Cは、新たに10×10の配列をメモリ上に用意します。今、や
りたいことはそれではないはずです。file()の中で用意された10×10配列
を扱いたいんですから。

nijigen[10][10]が正解なのは、nijigen[10][10]のところでは実際に
メモリ上に配列を用意するから正解なのです。

正解は、
char (*nijigen2)[10];
nijigen2 = file();

4.表示が転置されてる?
 printf("%c", nijigen2[a][b]);
となってますが、これだと縦がa+1番目、横がb+1番目の要素が
表示されますが良いんですか?

5.局所変数を戻り値にしている
 これは大問題です。file()の中の変数は、file()を出るときに全て解体され
ます。ということは、file()の中でメモリ上に作った10x10配列は、file()か
らreturnするときに消えてなくなります。したがって、ここは、nijigenを大
域変数として定義するのが良いでしょう。

~file.h~
...
static char nijigen[][10] = {
{'#', ..., '#'},
...};

6.ヘッダファイルの使い方がおかしい?
 ヘッダファイルには普通、関数の中身(定義)は書きません。もう少し規模
の大きいプログラムになると即問題が発生します。ヘッダファイルを複数の.c
ファイルから読み込んだときに、同じ名前の関数が2箇所で重複して定義され
ていることになります。変数も同様です。上のstaticというのは、この変数は
今の.cファイルの中だけの話しですよ、ということを示すことによって、
file.hが複数の.cファイルから読まれても大丈夫なようにしています。(その
代わり、読まれた回数だけメモリを消費します)

ふぅ。何にせよ、本を一冊買ってポインタの辺りを勉強することをお勧めしま
す。

私がこのコードを書くと下のように成ります。当然ながらベストとは言いませ
ん。私の好みということです。2次元配列をつくるための「10個のchar…ポイ
ンタ」はできるだけ使わない方が、char (*nijigen2)[10];みたいなややこし
い宣言を使わなくて済みます。

~file.h~

static const int RowNum = 10;
static const int ColNum = 10;

static const char nijigen[RowNum][ColNum] = {
{...},
...
};

~file.c~

int
main(int argc, char **argv)
{
int r, c;
const char *pointer = nijigen[0];

for( r = 0 ; r < RowNum ; r++ ){
for( c = 0 ; c < ColNum ; c++, pointer++ )
printf("%c", *pointer);
printf("\n");
}
}
    • good
    • 0

こんにちは。

 itohhといいます。

どのように、取り込もうとしたのかもう少し書いてください。
(2次元配列の定義部分や#include文の書き方など)

あと、うまくいかないとはどうなるのでしょうか?
(コンパイルエラーになる?実行時にうまく参照できない?)
このへんのことも、詳しく書いた方がアドバイスしやすいですよ。

この回答への補足

~file.h~
#include<stdio.h>
void file(){
char nijigenn[10][10]={{'#','#'・・・・・・'#','#'},
{'#','#'・・・・・・'#','#'},



{'#','#'・・・・・・'#','#'}};
return(nijigenn);
}
~file.c~
#include<stdio.h>
#include"file.h"
main(){
int a,b;
char nijigenn2[10][10];
nijigenn2=file();
for(b=0;b<10;b++){
for(a=0;a<10;a++){
printf("%c",nijigenn2[a][b])
}}
}
こんな感じで作ってみたんですけど、コンパイルが上手くできませんでした。
よろしくお願いします。

補足日時:2001/05/26 23:40
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


このQ&Aを見た人がよく見るQ&A