• ベストアンサー

ヘッダーファイルからの取り込みについて

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

  • da2
  • お礼率8% (5/58)

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.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++の言語仕様です。)

その他の回答 (2)

  • Fooky
  • ベストアンサー率71% (59/82)
回答No.2

確かに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"); } }

  • itohh
  • ベストアンサー率45% (210/459)
回答No.1

こんにちは。 itohhといいます。 どのように、取り込もうとしたのかもう少し書いてください。 (2次元配列の定義部分や#include文の書き方など) あと、うまくいかないとはどうなるのでしょうか? (コンパイルエラーになる?実行時にうまく参照できない?) このへんのことも、詳しく書いた方がアドバイスしやすいですよ。

da2
質問者

補足

~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]) }} } こんな感じで作ってみたんですけど、コンパイルが上手くできませんでした。 よろしくお願いします。

関連するQ&A

  • ヘッダーファイル

    初歩的な質問ですが、解答をお願いします。 VCで、簡単なプログラムを組んでいますが、ヘッダーファイルをコンパイルしようとすると… 「sengen.h」に関連したコンパイルツールが無いためコンパイルできません と出てきてしまいます。 どうすれば、ヘッダーファイルをコンパイルできますか?

  • Word ヘッダーの異なったファイルをひとつに

    ワードで、違うヘッダの入った二つのファイルを ひとつにまとめて、通しのページ数をつけて印刷する方法って ありますでしょうか?? コピペでひとつにまとめると、ヘッダがひとつになってしまうので 困っています。。。 ちなみに、旧ワードと、2007ワード両方とも使える環境にあります。 なにかいい方法御存知でしたら、教えてください。

  • ヘッダファイルとソースファイルについて

    今までは、Webプログラミングを行っていたのですが、 最近になって、C++の仕事を請け負いましたので、 C++を勉強しつつ、プログラムをしていたのですが、 Webプログラムとの違いに悩んでいる部分があります。 それは、ヘッダファイルとソースファイルの関係についてです。 ほかのファイルから、インクルードされたヘッダファイルが、 読み込まれるというのは納得がいくのですが、 そのヘッダファイルに関連付け(?)られたソースファイルも、 一緒に読み込まれるという理由がわかりません。 ヘッダファイルでソースファイルを読んでいるような記述もないような感じなので、とても疑問に思っております。 なぜ、ヘッダファイルをインクルードしただけで、付属のソースファイルも読み込まれるのでしょうか?

  • 自作ヘッダファイルについて (C言語)

    今ヘッダファイル自作について勉強しています。 ヘッダファイルの作り方、自作ヘッダファイルのインクルード方法などはわかったのですが、作ったヘッダファイルはどこに置けばいいのでしょうか?コンパイラは Visual C++ 2008 です。回答よろしくお願いします。

  • ヘッダファイルとソースファイルについて

    C++初心者なのですが ヘッダファイルとソースファイルの関係がよく分かりません。 ヘッダファイルとソースファイルはフリーソフトなどで、統合したりする事が出来るのでしょうか? よろしくお願いします!

  • ヘッダファイルの基本から作り方

    非常に基本的事かもしれませんが、意外とテキスト載ってないので聞きます。ヘッダファイル(stdio.hやctype.hなど最初からあるものを除く)の基本的役目ってなんですか?そして、これからより複雑なプログラムとなるとヘッダファイルを作成しなければいけないようですが、そのヘッダファイルのつくり方(ルールなど)をおしえてください。

  • ヘッダーファイルのインクルードについて

    こんにちは。ヘッダーファイルなどは使う命令によっていろいろなものをインクルードしなければなりませんが、最初に全てのヘッダーファイルをインクルードするのはだめなんでしょうか?教えてください。

  • VBScriptでCSVファイルを読み出したい

    現在VBScriptでCSVファイルを1行ずつ読み取って、2次元配列に格納するプログラムを作成しています。 CSVファイルの中身は、サンプルで shop,price,sales 001,500,700 003,1200,90 024,,18 という並びになっています。 実データは300件くらいです。 1行目のヘッダーを読み飛ばし、2行目のデータから1行ずつ読取、","でsplitを用いてまず1次配列に格納しています。 1次元配列のarrLine(0)=001、(1)=500、(2)=700と入ったデータを 2次元配列arrshopに順次保存?したいのです。 ---------------------------------------------- dim strLine '1行ずつ読込んだデータを持つ dim ntLineNum '行数のカウント dim arrLine '","で区切った要素を持つ一次元配列 dim arrshop '一次元配列になった要素を2次元配列として格納 Do until .AtEndOfStream   strLine = .ReadLine   if 0<>strComp("",Trim(strLine)) then ntLineNum = intLineNum + 1   end if   arrLine = split(strLine , ",")   arrshop = Array(arrLines,i) i = i + 1 loop ----------------------------------------- msgbox arrshop(2)(0) と指定すると「003」出るようにしたいです。 Array関数が上手くないような気もします・・・。 どなたかご教授お願いします(>_<。)

  • WAVEファイルのヘッダー等について

    現在WAVEファイルをバイナリで読み込み、チャンネルごとの情報(16進数)を配列に分けて入れたいと思っています。 サンプリングレートやデータサイズを読み込んだときに サンプリングレートなら44.1kHz ならば "44 AC 00 00"(16進数) とヘッダではなっていますよね? でも、実際は、44.1kHz = 44100Hz(10進数) = "00 00 AC 44" と逆です、ではチャンネルでもそうなのでしょうか? チャンネルはもしも3チャンネルだった場合(あまりないと思いますが。) 112233 112233…と並んでいるのでしょうか? それとも1111 2222 3333?でしょうか。 現在手元にソースがなく詳細を書けないのですが、WAVEファイルの全体構造について詳細なサイトや書籍等をご存知でしたら教えていただけると助かります。 よろしくお願いいたします。

  • 長いヘッダーを java外部ファイルにしたい

    ヘッダーのナビゲーションバーの部分を、 10個、全て画像のボタンをロールオーバーにしたいので、ソースの記述が多くなります。 全て共通のヘッダーなので、外部ファイル化したいのですが、 記述方法が、よくわかりません。 ヘッダー部分のXHTMLの記述をそのまま、javaファイルにコピペしてつくればよいのでしょうか? CSSもそのままでしょうか? "で囲む と、"前の¥など、他に、気をつけるべき点を教えてください。 よろしくおねがいします