画像(logo)

HOME/[C言語 入門]小学生でもわかるC言語3 目次/十一日目 ソース分割

広告

[C言語 入門 小学生でもわかるC言語3]
十一日目 ソース分割

広告

↓発売日:2018年09月22日↓

たった1日で基本が身に付く! C言語 超入門

新品価格
¥2,225から
(2018/10/8 23:10時点)

目次へ戻る

ソース分割

今回はソースの分割をやっていきたいと思います。

これができれば大きなプログラムもソースを分ける事によってすっきり見やすくなりますね!

前半はあまりよろしくない分割の仕方も中には含まれているので、ひとまずはそのように分割できるという事を学んでください。

後半にいくぶんマトモ?な分割の仕方をご紹介します。

/*十一日目 プログラム1*/
#include <stdio.h>

void hello_world(void);

int main(){
	hello_world();
		
	return 0;
}

void hello_world(){
	printf("hello world\n");
}

■実行結果■

画像(ci_11_1)

「hello_world」という関数が「hello world」するだけのプログラムです。

まずはこのプログラムを分割してみます。

簡単な分割

では一番シンプルな分割として関数の部分だけ分けてみましょう!

下準備として新しくソースファイルを追加します。

一番最初にソースファイルを作成した時と同じ手順で

画像(ci_11_2)

右側のソリューションエクスプローラー内のソースファイルを右クリック→追加→新しい項目を選んで

画像(ci_11_3)

「.cpp」ファイルを追加します。

いちよう名前が混同しないように「hello_world.cpp」という名前にしておきました。

「場所」の部分はそのままいじらないで大丈夫です。

もともとあるソースファイルの名前も右クリック→名前の変更で「main.cpp」という名前に変更しておきました。

画像(ci_11_4)

それでは分割をしていきます。

ファイル名「main.cpp」

/*十一日目 プログラム2その1*/
#include <stdio.h>

void hello_world(void);

int main(){
	hello_world();
		
	return 0;
}

ファイル名「hello_world.cpp」

/*十一日目 プログラム2その2*/
#include <stdio.h>

void hello_world(){
	printf("hello world\n");
}

■実行結果■

画像(ci_11_5)

これで分割完了しました。

関数本体の部分だけを移動しただけという感じですね。

なんだ簡単じゃん!と思われるかもしれませんが大事な点がいくつかあります。

プロトタイプ宣言

「main.cpp」の方にプロトタイプ宣言が必要になります。

これを書く事によって「void hello_world(void)」という関数がどこかにありますよ!と示す事になります。

#include <stdio.h>

いつものヘッダファイルが両方のファイルに書かれておりますが、これはとりあえず全てのファイルに書いておけばいいというものではありません。

あくまでも必要なので書いております。

試しに「#include <stdio.h>」を消してみると、

画像(ci_11_6)

「printf()」関数の部分に警告が現れるのが確認できるかと思います。

今まで一つのソースファイルだけでプログラムを組んでいたので、「意味はわからないけどとりあえず書いとけばいいやー!」ですましていた事もこれからは通用しません。

関数や命令一つ一つを噛みしめながらプログラムを書いていきましょう!

※正確に言いますと今回の場合は「main.cpp」の方の「#include <stdio.h>」は必要ないのですが、なんとなくサマにならないので記述しております。

複数の関数を書く事も可能です。

ファイル名「main.cpp」

/*十一日目 プログラム3その1*/
#include <stdio.h>

void hello_world(void);
void goodby_world(void);
void thankyou_world(void);

int main(){
	hello_world();
	goodby_world();
	thankyou_world();
		
	return 0;
}

ファイル名「hello_world.cpp」

/*十一日目 プログラム3その2*/
#include <stdio.h>

void hello_world(){
	printf("hello world\n");
}

void goodby_world(){
	printf("goodby world\n");
}

void thankyou_world(){
	printf("thankyou world\n");
}

■実行結果■

画像(ci_11_7)

別に一つのファイルに一つの関数というワケではなく、同じ手順で複数の関数を記述する事ができます。

さらに分割された方のファイルにプロトタイプ宣言を書いて、また他に用意した方のファイルに本体を書く事もできます。

新しく「hello_world2.cpp」というソースファイルを追加しております。

ファイル名「main.cpp」

/*十一日目 プログラム4その1*/
#include <stdio.h>

void hello_world(void);

int main(){
	hello_world();
		
	return 0;
}

ファイル名「hello_world.cpp」

/*十一日目 プログラム4その2*/
#include <stdio.h>

void goodby_world(void);
void thankyou_world(void);

void hello_world(){
	printf("hello world\n");
	goodby_world();
	thankyou_world();
}

ファイル名「hello_world2.cpp」

/*十一日目 プログラム4その3*/
#include <stdio.h>

void goodby_world(){
	printf("goodby world\n");
}

void thankyou_world(){
	printf("thankyou world\n");
}

■実行結果■

画像(ci_11_8)

ややこしくなるのでこのような分割の仕方はあまりする事はないと思いますが、これでプロトタイプ宣言が「int main()」になくてはならないというワケではない事がわかりますね!

ただ、この状態で「main.cpp」から直接「goodby_world()」関数や「thankyou_world()」関数を読み出そうとしても、プロトタイプ宣言がないので呼び出す事はできません。

広告

マトモな分割

ここまでの分割の仕方だけでも小規模なプログラムなら対応できそうですが、中規模、それ以上のプログラムともなると「int main()」もしくは関数本体が書いてあるファイルに混同してプロトタイプ宣言がずらずらと並んでいるのはあまりよろしくない気がしますよね。

そこでヘッダファイルというものを使います。

いつも先頭に書いている「#include <stdio.h>」みたいなのを自分でも作ろうというワケです。

ヘッダファイル

ヘッダファイル、その役割はプロトタイプ宣言、構造体変数宣言、定数宣言、などなど主に宣言にあたいするものをここには書いていきます。

という事は今まで「int main()」などに書いていた分割した関数のプロトタイプ宣言、あれも本来はこちらに書いていくという事なんですね。

なので関数本体があるファイル、そのプロトタイプ宣言があるヘッダファイルを対になるようなカタチで作っていきます。

下準備として同じような手順で今度はヘッダファイルを追加してください。

右側のソリューションエクスプローラー内のヘッダファイルを右クリック→追加→新しい項目を選んで

画像(ci_11_9)

ヘッダファイルを追加します。

画像(ci_11_10)

名前は「hello_world.h」にしました。

名前もその関数本体に合うようにつけます。

それではヘッダファイルも含めた分割をしていきます。

ファイル名「main.cpp」

/*十一日目 プログラム5その1*/
#include <stdio.h>
#include "hello_world.h"

int main(){
	hello_world();
	goodby_world();
	thankyou_world();
		
	return 0;
}

ファイル名「hello_world.h」

/*十一日目 プログラム5その2*/
void hello_world(void);
void goodby_world(void);
void thankyou_world(void);

ファイル名「hello_world.cpp」

/*十一日目 プログラム5その3*/
#include <stdio.h>

void hello_world(){
	printf("hello world\n");
}

void goodby_world(){
	printf("goodby world\n");
}

void thankyou_world(){
	printf("thankyou world\n");
}

■実行結果■

画像(ci_11_11)

これでプロトタイプ宣言もまとめる事ができてスッキリしましたね!

「main.cpp」の先頭で

#include "hello_world.h"

今作ったヘッダファイルをインクルードする事によりその中の関数群を使えるようになります。

自作ヘッダは「"」で囲むトコロに注意です。

「#include」とは

自作ヘッダも作れるようになったトコロで「#include」するとはどういう事なのかを今一度考えてみます。

今まではファイルを取り込むみたいな言い方をしてきたので、何かスゴイ事をしているようなイメージのある「#include」ですが、実を言いますとこの命令はその指定されたファイルの内容をペタっと貼り付けているにすぎません。

たとえば先ほどの例で言いますと

#include <stdio.h>
#include "hello_world.h"

int main(){
	hello_world();
	goodby_world();
	thankyou_world();
		
	return 0;
}

この「#include "hello_world.h"」と記述された部分にその内容を貼り付けているだけなので

#include <stdio.h>

/*#include "hello_world.h"の内容を*/
/*↓貼り付け↓*/
void hello_world(void);
void goodby_world(void);
void thankyou_world(void);

int main(){
	hello_world();
	goodby_world();
	thankyou_world();
		
	return 0;
}

こんな感じの事をしているだけなのです。

ここで勘違いしないで頂きたいのが、あくまでも貼り付けられているのはその指定されたヘッダファイルの内容というだけであって、その本体にあたる

「hello_world()」

「goodby_world()」

「thankyou_world()」

は別のファイルのままというトコロに注意してください。

次回グローバル変数の扱い方や2重定義を防ぐインクルードガードというものを扱うにあたりここを勘違いしたままだとけっこうハマります!!!

「インクルードして貼り付けられているだけの部分」と「別のファイルに分かれている部分」の違いに気をつけましょう!

構造体、定数など

構造体変数宣言、定数宣言などをヘッダファイルに分割した例です。

ファイル名「main.cpp」

/*十一日目 プログラム6その1*/
#include <stdio.h>
#include "my_header.h"

int main(){
	struct PLAYER p;
	int ary[HEIGHT][WIDTH] = {
		{9,9,9,9,9,9,9,9,9,9},
		{9,0,0,0,0,0,0,0,0,9},
		{9,0,9,9,9,9,9,9,9,9},
		{9,0,0,0,0,0,0,0,0,9},
		{9,9,9,9,0,9,9,9,0,9},
		{9,0,9,0,0,0,0,0,0,9},
		{9,0,9,9,9,9,9,9,0,9},
		{9,0,0,0,0,0,9,0,0,9},
		{9,0,9,9,0,0,0,0,9,9},
		{9,9,9,9,9,9,9,9,9,9},
	};
	int x,y;

	p.x = 1;
	p.y = 8;

	ary[p.y][p.x] = 1;

	for(y=0;y<HEIGHT;y++){
		for(x=0;x<WIDTH;x++){
			if(ary[y][x] == 9){
				printf("□");
			}
			else if(ary[y][x] == 1){
				printf("P");
			}
			else{
				printf(" ");
			}
		}
		printf("\n");
	}
		
	return 0;
}

ファイル名「my_header.h」

/*十一日目 プログラム6その2*/
#include "define.h"
#include "struct.h"

ファイル名「define.h」

/*十一日目 プログラム6その3*/
#define WIDTH 10
#define HEIGHT 10

ファイル名「struct.h」

/*十一日目 プログラム6その4*/
struct PLAYER{
	int x;
	int y;
};

■実行結果■

画像(ci_11_12)

このようにヘッダファイルをまとめたヘッダファイルを作ってそれをインクルードするようなやり方もあります。

ヘッダファイルやプロトタイプ宣言の意味を確認しながらいろいろ試してみてください。

それでは次回は分割したソースファイル同士での変数の受け渡しなどを見ていきたいと思います。

次回

十二日目 ソース分割2

□ページの先頭へ□

□目次へ戻る□

□HOME□

広告

↓発売日:2016年02月29日↓

12歳からはじめる ゼロからのC言語 ゲームプログラミング教室

新品価格
¥2,462から
(2018/10/8 23:25時点)

↓発売日:2018年06月22日↓

スッキリわかるC言語入門

新品価格
¥2,916から
(2018/10/8 23:15時点)

↓発売日:2018年03月09日↓

C言語本格入門 ~基礎知識からコンピュータの本質まで

新品価格
¥3,218から
(2018/10/8 23:16時点)

↓発売日:2017年06月14日↓

やさしいC 第5版 (「やさしい」シリーズ)

新品価格
¥2,700から
(2018/10/8 23:17時点)

↓発売日:2018年05月21日↓

作って身につく C言語入門

新品価格
¥2,462から
(2018/10/8 23:18時点)

↓発売日:2017年12月07日↓

新・標準プログラマーズライブラリ C言語 ポインタ完全制覇

新品価格
¥2,678から
(2018/10/8 23:19時点)

↓発売日:2017年02月08日↓

新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ)

新品価格
¥2,700から
(2018/10/8 23:20時点)

↓発売日:2017年09月26日↓

かんたん C言語 [改訂2版] (プログラミングの教科書)

新品価格
¥2,916から
(2018/10/8 23:22時点)