こんにちは､ ようこそ｡
新コーナーをスタートします｡
私たちのセクションは､ 機能をベースにしています｡
そこで､ まずは関数の基本的なことをいくつかお話しします｡
関数とは､ 特定のタスクを達成するために設計された自己完結型のプログラムコードの単位であり､
これが高度な定義です｡
関数とは､ 基本的に､ コードの重複を減らすために呼び出すものです｡
しかし､ これはコード自体の中で自己完結しており､
達成すべきタスクがいくつかあるだけです｡
構文規則は､ 関数の構造とその使い方を定義することになる｡
そのため､ 使用するプログラミング言語によって､ 関数の定義が異なる場合があります｡
cについては､ 具体的なルールの話をします｡
ほとんどのプログラミング言語がこの関数の概念をサポートしているので､ その利点とサポートされる理由をお伝えします｡
cの関数は､ 他のプログラミング言語におけるサブルーチンやプロシージャと同じものです｡
よくサブルーチンやプロシージャという言葉を聞きますが､ これは関数と同じものです｡
あるコードを実行する自己完結型のユニットで､ 呼び出すことができる｡
ある機能は､ アクションを起こします｡
だから､ ここまでの2､ 3の機能は熟知しているのです｡
printf関数は､ アクションを起こす出力を画面に表示する関数で､
何かをしてくれる関数です｡
そしてその結果､ キーボードからの入力を受け取るscanf関数も見てきました｡
ここでも､ ある意味､ 別の作用が働いているのです｡
しかし､ 他の関数は､ 実際には､ プログラムが使用する値を見つけるだけです｡
ですから､ 例えば文字列や文字配列を勉強するときには､ 文字列の操作や物事の変更を行うための関数を調べます｡
特にstir lengthという関数があり､ これはある文字列の長さをプログラマーに教えてくれる｡
アクションを起こすわけではなく､ 情報を返すだけです｡
つまり､ 関数はプログラムで達成しなければならないタスクに応じて､
アクションを起こしたり､ プログラムの値を変更したり､
値を返したり､ ステータス情報を伝えたりするタスクを実行します｡
機能の優位性
関数を使うのは､ たくさんの利点があるからです｡
機能は､ 分割統治戦略を可能にします｡
だから､ もしあなたが中型のプログラムや大型のプログラムを書いて行ったとしたら､
本当に､ 本当にメンテナンスが大変になりますよ｡
大きな関数が1つあると､ テストやデバッグ､ エラーの発見や修正が大変になります｡
このように分解して､ 分割統治することで､ コードのバグを発見し､
修正することが非常に容易になるのです｡
そして､ 1つのCプログラムでmain関数しかなく､ 5000行もあるのを想像できますか？
その問題をどう攻略すればいいのか､ 手がかりがないのです｡
本当に､ お粗末な組織です｡
結束力がなく､ ただひたすら問題解決に飛び込んでいくような状態ですね｡
そこで､ 関数を使うことにします｡
分割統治とは､ 基本的にタスクをいくつかの独立したサブタスクに分割できることを意味します｡
コード全体の複雑さを軽減することができます｡
サブタスクごとに別々の関数を作成し､ さらに関数を作成してサブタスクを分割することも可能です｡
こうした追加機能を作るたびに､ 複雑さが軽減されます｡
このような関数を作成し､ 分割統治戦略を用いる場合の目標は､
関数をできるだけまとまりのあるものにすることです｡
つまり､ 各機能が1つのタスクだけを行うようにし､ 1つの機能で5つ､ 10ものタスクを行わせないようにするのです｡
キーボードからの入力を読み取る関数を書く場合､ キーボードからの入力を読み取らせ､
文字列をチェックしたり､ 出力を表示したりするようなことはさせないようにします｡
機能は小さく､ そして非常にまとまりが必要です｡
しかし､ 分割統治戦略は､ その複雑さを軽減してくれるので､
本当にありがたい｡
5000行のコードを持つメイン関数を持つ代わりに､ 特定のタスクを行う多くの関数を持つことができ､
それらを非常に迅速に識別することができます｡
だから､ 関数はコードの重複を減らすことになる｡
また､ コードの重複を減らすと､ そのコードを書いたり､ テストしたり､
デバッグしたりする時間を短縮することができます｡
また､ ソースコードのサイズも再縮小することになります｡
なぜ関数がコードの重複を減らすかというと､
あるタスクを何度も何度も繰り返して同じコードを書く代わりに､
そのタスクを関数にカプセル化して､ 関数を呼び出せば､
その関数が毎回やってくれるから､ 重複がないんですね｡
ある作業をプログラムの中で何度も行う必要がある場合､
先ほど述べたように適切な関数を一度だけ書けばよいのです｡
そのコードを何度も書く必要はないのです｡
そのため､ プログラムは必要なときにいつでもその関数を使うことができます｡
また､ 同じ関数を別のプログラムで使うこともでき､ それがライブラリの構成要素となっています｡
今までは､ 標準入力出力ライブラリのprintf関数を使っていたんだ｡
そして､ それは一度しか書かれていないのに､ 何度も何度も呼び起こすのです｡
もしその関数がなかったら､ その関数の実装をプログラムに取り込んで､
ひたすらそれを繰り返すしかないんです｡
そのため､ 関数は多くの時間を節約し､
ソースコードを減らし､ 何度でも再利用することができるのです｡
つまり､ ソフトウェアの再利用技術でもあるんですね｡
また､ 読みやすさにも貢献します｡
プログラムをモジュール化し､ 特定のタスクを実行するための個別の関数を作成すると､
プログラムがよりよく整理されます｡
先ほども言ったように､ メインルーチンやメイン関数があり､ その中に大量のコードがある場合､
5つの関数を呼び出し､ それらの関数が特定のタスクを行うメインルーチンに比べて､
フォローするのがずっと難しくなってしまうでしょう｡
だから､ プログラム編成に役立つのです｡
プログラムのメンテナンスに役立ちます｡
その方が読みやすいし､ どんなソースコードでも変更・修正しやすいからです｡
そして､ 保守フェーズはソフトウェアのライフサイクルの中で最も費用がかかるフェーズであることを忘れないでください｡
このフェーズでは､ バグを修正し､ プログラムがリリースされ､ 新しい機能が追加されるところです｡
プログラムの構成が良ければ良いほど､ 維持が容易になります｡
このように､ ソースコードの整理､ 読みやすさ､ 何が起こっているのかを把握することは非常に重要で､
機能面でも非常に役立ちます｡
また､ 分割統治方式では､ プログラムの一部を独立して開発､
テスト､ デバッグすることができる｡
現実の世界に出て､ コードを書き始めると､ プログラムは本当に､
本当に大きいということに気がつくでしょう｡
そして､ これらのプログラムには､ 何百人､ 何千人という人々が関わっています｡
一つのプログラムに多くの人が参加する場合､
分割統治方式で小さな作業を独立させると､
より簡単に作業ができます｡
同じソースコードを触っているわけではないので､ より簡単にタスクを実行に移せます｡
そして､ このように複数の人がプロジェクトに参加することで､
全体の開発期間を短縮し､ メンテナンスコストや開発コストを削減することができるのです｡
また､ 機能の再利用も可能で､ これも時間短縮につながります｡
そしてまた､ printf関数でそれを行い､ 再利用するのです｡
しかし､ 自分でユーザー定義関数を書くと､ プログラムの中で何度も再利用することができるんだ｡
ですから､ ソフトウェアの再利用は､ 機能の大きな大きなメリットです｡
これらの機能を考えるとき
関数でプログラムを設計するもう一つの良い点は､ プログラムをブラックボックスとして考えたいことです｡
ブラックボックスとして考えたときの意味は､ 関数への入力と出力しか考えていないということです｡
また､ アウトプットの中のインプットだけに注目すると､ 実装を始める前にデザイン全体を見渡すことができます｡
そして､ 機能全般がデザインに集中できるような､ このような思考になるのです｡
そして､ デザインが重要であることを述べました｡
設計とは､ プログラムをどのように構成するか､ どのようにコードを書くか､
といった計画を立てることです｡
そして､ このプランニングは､ コードを書くという実装を始める前に行うことが重要です｡
そして､ 関数を考え､ 入力と出力だけを考えることで､ プログラムがどのように構成され､
どのような関数を作ればいいのかを考えることができるのです｡
だから､ 細かいところでの実装だけを気にする必要はないのです｡
そして､ これは重要なことです｡ なぜなら､ コードを書く前にまずしたいことは､
デザインについて考えることだけで､ 実装について考え始めたくはないのです｡
初めてコードを書くときに､ 多くの学生が抱える問題は､
ただ実装を始めてしまうことです｡
問題を考えず､ どう解決するかも考えず､
ただコードを書き始めるのです｡
決して良い方法とは言えません｡
コードや関数を書こうと思ったときに､ 関数の入力と出力だけで考えてみると､
設計の助けになりますよ｡
では､ いくつかの例を見てみましょう｡
これまでにも､ printfやscanfといった組み込み関数を使用してきました｡
それらは､ プログラミング言語cが提供する標準入力出力ライブラリの中にある｡
しかし､ 関数をどのように定義するか､ 関数にどのようにデータを渡すか､
といった細かい点についてはまだ理解していません｡
しかし､ printf関数では､ データを受け取ることに気がついたはずです｡
関数にデータを渡すことができます｡
データは､ 関数名に続く括弧の間の引数である｡
引数とパラメータについては､ また別の講義で詳しく説明する予定です｡
しかし､ 高いレベルでは､ 関数にデータを渡すことができることを理解してください｡
そして､ printf関数を見ることでそれを理解する｡
printf関数の最初の引数は､ 文字列リテラルで､
二重引用符で囲まれたすべての文字が渡されるデータです｡
また､ 引数には0個のものもあれば､ 値が表示される変数や式を並べた変数引数もありました｡
つまり､ 最初の引数に書式指定子があれば､ それ以降の引数には､
このような変数があることを思い出してください｡
では､ printf関数にデータを渡すことはできたのでしょうか｡
また､ 関数から情報を受け取り､ データを返すことができることにもお気づきでしょう｡
scanf関数では､ データをどのように保存するかということが引数の1つでした｡
そして､ その変数に､ ユーザーがキーボードで入力した値を渡すのです｡
つまり､ 関数の戻り値のようなものだと考えればいいわけです｡
ですから､ 関数はデータを取り込んで､ そこからデータを返すことができるので､
非常に価値のあるものです｡
関数のコーディングの例ですが､ これは単に呼び出すだけの関数ですが､
これがメイン関数です｡
プログラムの入り口である主要な関数についてはよく知られています｡
でも､ 見てください､ この素敵さを｡
関数read list sortとaverageを呼び出しています｡
3行のコードしかないのです｡
その機能を実装しに行かなければならないのですが､ このプログラムは何をしているのかがすぐにわかるので､
プログラムが整理されます｡
このプログラムは､ リストを読み込み､ リストをソートし､
リストの平均を表示するもので､ リストには浮動小数点が含まれています｡
だから､ とても読みやすく､ メンテナンスもしやすい｡
もしプログラムにバグがあれば､ そのバグの見つけ方､ 切り分け方がすぐにわかるようになるのです｡
バグでソートされないならソート機能へ
もしバグが平均化にあるのなら､ 平均化関数に行けば､ 非常に簡単にエラーを切り分けることができます｡
ですから､ 前のスライドでこれらの関数を実装したときは､
ただ呼び出すだけでした｡
実際に関数を実装するには､ 関数本体の中にコードを書かなければならない｡
printfのようなc言語が実装している関数を利用することもできますし､
ユーザー定義関数を独自に作成することもできます｡
printf関数やライブラリにある関数を実装する必要はなく､
自分で作った関数を実装するだけです｡
ですから､ この前の例では､ 読み取りリストのソートと平均を使ったので､
この関数を実装する必要がありました｡
リストの読み込み､ リストのソート､ リストの平均化を実際に行う関数ヘッダー､
関数本体を提供しなければならない｡
機能を定義しただけで終わりではなく､ それを実装しなければならないのです｡
また､ 機能を実装する際には､ プログラムが何を行い､
どのように構成されているかを明確にするために､ 常に説明的な関数名を使いたいものです｡
前の例では､ read listという名前の関数がありましたが､ これは何をするものなのか､
関数名sortは明らかです｡
関数にx､ y､ zという名前をつけていない｡
その機能を説明しました｡
変数を記述したり､ 作成したりするときも同じで､
意味のある名前です｡
また､ これらの関数を汎用的なものにして､ 実際に何かをしたり､
汎用的なデータを受け取ったりできるようにすれば､ ライブラリ関数のように他のプログラムでも再利用できるようになるでしょう｡
ここでも､ ソフトウェアの再利用をサポートします｡
そこで､ これからの講義では､ 関数を定義する方法､
具体的な構文､ 関数の呼び出し方､ 関数のデータの受け渡し方法について説明します｡
これからの講義では､ そこに注目することになります｡
また､ どのC言語プログラムでも何度も目にしてきたメインルーチン､
それは関数であることもお伝えしておきます｡
main関数は､ cシステムで特別に認識されている名前で､
プログラムの実行を開始する場所を示しています｡
すべてのcプログラムは必ずmainを持っています｡
main関数は､ コマンドラインの引数を渡すとデータを取ることができますし､
データを取る必要はありません｡
また､ オプションで返すことができるデータもあります｡
0を返すメイン関数を使用していることに気づくだろう｡
通常､ エラーコードを返したいときに使う｡
しかし､ すでに特定の関数を使用しており､ 最も重要な関数はそのmain関数で､
これもまたコードの整理に役立ちます｡
メインを探すだけなので､ プログラムのスタート地点は常に分かっています｡
これは､ 関数の利点や関数とは何かを特定するような､
関数のハイレベルな説明です｡
さて､ 次は実装の話です｡
ありがとうございます｡