パート6:ファイルを分割する
 CipherTextに関連する部分をmain.cファイルから分離してみましょう。
CipherText.c

 というC言語テキストファイルを用意し、そちらにstringlen、initCipherText、deleteCipherText、cipher、decipher関数を移動させる事にします。
main.c

 にはmain関数のみを残します。
 CipherText構造体はCipherText.c、main.cの両方のファイルで必要とされるので、CipherText.cのヘッダーファイルとして
CipherText.h

 を用意し、その中でCipherText構造体の定義、initCipherText、deleteCipherText、cipher、decipher関数宣言をおこない、CipherText.c、main.cの両方で#includeして共有します。

テン*シー*シー-1

 #includeで<>ではなく""を使っている事に注意してください。これから作成するCipherText.hファイルは自分のプロジェクトに登録するファイルなので<>を使うと見つかりません。

CipherText.h
 まずはCipherText.hファイルをプロジェクトに追加しましょう。
 File→New→New File…メニューを選んでください。
 ファイルテンプレート選択画面が現れるので、Mac OS XのC and C++タブを選び、Header Fileテンプレートを選びNextボタンを押します。

テン*シー*シー-2

 次の画面ではファイルの保存場所や、登録するプロジェクトターゲットやグループを聞いてきます。
 名前を
CipherText.h

 とし、 場所はstudyフォルダ内、Groupはstudy、Targetsのstudyにはチェックを入れてCreateボタンを押してください。

テン*シー*シー-3

 これでCipherText.hがstudyプロジェクトに登録されます。

テン*シー*シー-4

 続けてCipherText.cファイルもプロジェクトに追加しましょう。
 先ほどと同じくFile→New→File…メニューを選んでください。
 ファイルテンプレート選択画面で、Mac OS XのC and C++タブを選び、C Fileテンプレートを選びNextボタンを押します。

テン*シー*シー-5

 次の画面では名前をCipherText.cとし、後はCipherText.hと同じにしてCreateボタンを押してください。

テン*シー*シー-6

 これでCipherText.cもstudyプロジェクトに登録され準備完了です。

$テン*シー*シー-9

 main.cとCipherText.cがコンパイルされ、リンクされる事になります。

$テン*シー*シー-8

 準備ができたので分割作業に入りましょう。
 まずはmain.cからCipherText.hにCipherText構造体定義を#ifndef study_CipherText_h~#endifの間にカット&ペーストしてください。

 CipherText.hにあらかじめ記述されていた
#ifndef study_CipherText_h
#define study_CipherText_h

#endif

 は2重読み込みを防止するための仕掛けです。
#ifndef

 はプリプロセス指令で、右にある単語study_CipherText_hが#defineで定義されていない場合のみ、そこから
#endif

 までの記述を有効にするという意味です。
 無効の場合は、注釈と同じく取りはぶかれます。
 例えばmain.cに#include "CipherText.h"が2回記述された場合
#include "CipherText.h"
#include "CipherText.h" ←2回目

 最初の差し替え部分ではstudy_CipherText_hが#defineされていませんが、次以降の差し替え部分ではstudy_CipherText_hが#defineされているので、注釈と同じく取りはぶかれてしまうわけです。

テン*シー*シー-7

 上の極端な例のように、ひとつのファイル内で同じファイルを2回#includeしてしまうような人はあまりいないでしょうが、#include命令は、その読み込み先のヘッダーファイル内でも使われている可能性があり、自分が気づかずに同じヘッダーファイルを2回#includeする事はよく発生します。


 そして、main関数でも使うinitCipherText、deleteCipherText、cipher、decipher関数の宣言をおこないます。
#ifndef study_CipherText_h
#define study_CipherText_h
typedef struct {
int shift; // ずらし量
char* text; // 暗号化された文字列
} CipherText;

void initCipherText(CipherText* cipher);
void deleteCipherText(CipherText* cipher);
int cipher(const char * plain_text, int shift, CipherText * cipher);
char* decipher(const CipherText * cipher);

#endif
CipherText.h

 次にmain.cからCipherText.cにmain関数以外をカット&ペーストします。その後、stdlib.h、CipherText.hを#includeして、CipherText.hで関数宣言した関数はstaticを外します。
#include <stdio.h>
#include <stdlib.h> ←malloc,freeを使うので追加
#include "CipherText.h" ←CipherText構造体や、各関数宣言を使うので追加


static int stringlen(const char* text)
{
・・・
}
void initCipherText(CipherText* cupher) ←staticを外す。
{
・・・
}
void deleteCipherText(CipherText* cupher) ←staticを外す。
{
・・・
}
int cipher(const char * plain_text, int shift, CipherText * cipher)←staticを外す。
{
・・・
}
CipherText.c

 最後にmain.c側にもCipherText.hを#include しておしまいです。
#include
#include <stdlib.h>
#include "CipherText.h" ←CipherText構造体や、各関数宣言を使うので追加

int main (int argc, const char * argv[])
{
・・・
}
main.c

サンプルプロジェクト:study-21-cipher-div.zip

 Runすると今までどおり実行されます。

 CipherText.c、CipherText.hファイルを用意する事で、この暗号化関数群は別のプロジェクトでも利用しやすくなりました。
 アプリケーションは、このように機能ごとにファイルを分散させて作るのが一般的です。
 暗号化の処理が複雑になるとCipherText.c自体を同じ要領でいくつかのファイルに分割したりもします。
 staticの付いているstringlen関数をmain.c側でも記述するとどうなるかなど、いろいろ試して、これまで学習した内容を検証してみてください。

 これでC言語の学習は一応の区切りとします。
 次の章では、C言語中級レベルの関数ポインタ、そしてオブジェクト指向についてちょっとだけ話します。