コンピュータにおけるプログラムとは問題を解くための処理手順を表す。プログラミング言語とはこのプログラムを人間が使用する自然言語に近い文法で表記できるようにしたものであり、テキストコードで記述するのが一般的である。逆にコンピューターが解釈実行するプログラムを機械語と呼び、通常はバイナリコードで表示される。プログラミング言語は抽象度が高く人間が理解しやすい高水準言語と機械語に近く、コンピューターの処理を直接記述する低水準言語に分類される。
高水準言語ではかつて手続き型言語が主流であったが、現在ではこれをよりモジュール化が可能になったオブジェクト指向言語が主流になっている。
プログラムを一定の動作ごとにルーチン化し、必要に応じてこのルーチンを呼び出すことで処理をおこなう機能を持ったプログラム言語。ルーチンの呼出し元への戻り先の管理にはスタック領域が用いられる。
プログラムを機能ごとにクラス化し、必要に応じてこのクラスをインスタンスとして生成する機能を持ったプログラム言語。クラス間の関係性はヒープ領域で管理される。
プログラムによる処理の流れを記号を用いて図式化したもの。視覚的に処理内容を理解することができる。
フローチャートを構成する基本的な記号は以下のようになる。
フローの始まりと終わりは端子記号を用いて開始と終了がわかるようにする。 記号の中は”Start”や”End”あるいは”開始”や”終了”と記述する。
外部からのデータの入力または出力を表す。
通常は実際に入出力されるデータ項目に対し”Bを入力”、”Bを出力”と記述する。
条件を判断し、それ以降の流れを分岐させるために用いる。 分岐は通常二つで条件が「真」になる場合 (「YES」、「true」、「はい」と表記してもよい)と 「偽」になる場合 (「NO」、「false」、「いいえ」と表記してもよい)を表記する。 判断の内容は等号、不等号で記述するか、 比較演算子(関係演算子)と論理演算子で表現する。
演算や代入をなどの処理の内容を表す。
通常、演算は算術演算子*で表現し、値を変数*に代入*する場合は”←”で表記する。
変数や定数*の宣言*および初期値設定を記述する。
一定の条件下で同じ処理を繰り返す処理を表現する。 条件式は判断記号と同じ表記法か初期値、カウンタステップ数、終値を表記する。 繰返しはこの記号を用いず、判断のフローを応用して利用することもある。
変数と配列はともにプログラムが扱うデータを保持しておくメモリ上の格納領域のことを指す。
アドレス | A | B | C | D |
---|---|---|---|---|
1 | 26 | 31 | 18 | 20 |
2 | 3647 | 67814 | 13 | 99 |
3 | 10 | 6598 | 92546 | 75 |
4 | 100 | 2654 | 25 | 65115 |
アドレス | A | B | C | D |
---|---|---|---|---|
1 | 26 | 31 | 18 | 20 |
2 | 3647 | 67814 | 13 | 99 |
3 | 10 | 6598 | 92546 | 75 |
4 | 100 | 2654 | 25 | 65115 |
フローチャートにより構成されるロジックのなかで、一般的に採用されるフローを構造化プログラミングと呼ぶ。
ロジックがスパゲティーコード*になるのを防ぐためにプログラムはこのような規則性に則って記述される必要がある。
フローの通り、順番に処理を実行していくプログラム構造。
フローの中で条件判断が実行され、その判断により処理が分かれるプログラム構造。
フローの中で処理が繰返し実行され、一定の条件で反復が終了するプログラム構造。
プログラムとは論理とデータで成り立つ。現実の事象を表すデータとこれを処理する手続きを手順化するのがプログラムである。アルゴリズムはこの手順を定式化、最適化したものでありデータ構造はデータをプログラムが利用できるように配置、管理する方法である。
最大公約数を求めるためのアルゴリズム。暗号化プログラムで主に用いられる。
文字列の中から、キーとなる文字列の位置を取得する文字列探索アルゴリズム。
隣接行列(経路)から、最短経路を導き出す最短経路探索アルゴリズム。
ゴールまでの推定値を用意することでより少ない計算量で最短経路を導き出すアルゴリズム。
配列などから探索条件となるキー値の位置を探索するアルゴリズム。
後入れ先出し(Last In First Out)もしくは先入れ後出し(First In Last Out)形式でデータが格納される方式。手続き型言語の関数の呼び出し時に呼び出し元の関数の状態保持のためにスタック領域で管理される。
先入れ先出し(First In First Out)形式でデータが格納される方式。タスクの状態遷移などで実行可能状態のタスクを保持するために主に利用される。
データの並びを任意の順番で配置することができる方式。配列などで利用される。他のデータ構造はこのリストですべて実装することができる。
データを根(root)と節(node)または葉(leaf)で持つことでデータに階層構造を与え、検索を容易にする方式。オブジェクト指向言語のオブジェクトはツリーで構成されたヒープ領域で管理される。
プログラムにおいて繰返し利用されるコード(ルーチン)を手続き化して機能別に分割できるようにしたもの。
通常は主たるルーチン(メインルーチン)が従属するルーチン(サブルーチン)を呼び出す形でコードが記述される。
戻り値 関数名(引数,…){ 処理 }
その関数が処理の終了後に出力する変数の型*を指定する。
関数を呼び出す際に指定する名前を定義する。
関数が処理にあたって必要とする入力データの個数と型を指定する。
※例(C言語)
/* 半径5cmの円の面積を求める */
main(){
int radius = 5;
int area;
area = subroutine(radius); /* 半径から面積を求める関数を呼び出す */
printf("Area = %d",area);
}
/*
* 半径から面積を計算
* 引数:半径
* 戻り値:面積
*/
int subroutine(int r) {
int a;
a = r * r * 3.14159;
return a;
}
変数、または関数を参照することができる範囲の定義をスコープという。
メモリ領域の確保のため変数はライフタイムをもち、一定のタイミングでメモリから破棄される。
対象となる変数や関数に対しすべてのスコープから参照が可能。
プログラムロード時に一度だけ初期化され以後、プログラムが破棄されるまでメモリ上に存在する。
対象となる変数や関数は定義した関数など限定されたスコープでのみ参照可能。 関数処理時に初期化され、関数の実行終了とともに破棄される。
※例(C言語)…上記とは円周率をグローバル変数化しているところが異なる。
double pi = 3.14159; /* グローバル変数(mainとsubroutineで利用可能) */
/* 半径5cmと直径10cmの円の面積を求める */
main(){
int radius = 5; /* ローカル変数(mainでのみ利用可能) */
int diameter = 10;
int area;
area = subroutine(radius); /* 半径から面積を求める関数を呼び出す */
printf("Area = %d",area);
area = (diameter / 2) * (diameter / 2) * pi; /* 直径から面積を求める */
printf("Area = %d",area);
}
/*
* 半径から面積を計算
* 引数:半径
* 戻り値:面積
*/
int subroutine(int r) {
int a; /* ローカル変数(subroutineでのみ利用可能) */
a = r * r * pi;
return a;
}
プログラムロード時に一度だけ初期化され以後、プログラムが破棄されるまでメモリ上に存在する。 スコープはグローバル、ローカルそれぞれに合わせる。
※例(C言語)…上記とは円周率をローカルで静的変数化しているところが異なる。
/* 半径5cmと直径10cmの円の面積を求める */
main(){
int radius = 5;
int diameter = 10;
int area;
area = subroutine(radius); /* 半径から面積を求める関数を呼び出す */
printf("Area = %d",area);
area = (diameter / 2) * (diameter / 2) * 3.14159; /* 直径から面積を求める */
printf("Area = %d",area);
}
/*
* 半径から面積を計算
* 引数:半径
* 戻り値:面積
*/
int subroutine(int r) {
static double pi = 3.14159; /* 静的変数(プログラムロード時に領域確保) */
int a; /* 自動変数(subroutineの呼び出し時に領域確保) */
a = r * r * pi;
return a;
}
※グローバル変数の利用に関する問題
グローバル変数を利用する場合、コード自体や関数での個別の値の変更に他の関数も影響を受けるという問題がある。
グローバル変数は多用せず、関数間で横断的に利用されるデータは関数の引数と戻り値を介して受け渡しされるのが望ましい。
※例(C言語)…関数の中で円周率を再定義しているが、後続の関数には影響を与えない
/* 半径5cmと直径10cmの円の面積を求める */
main(){
double pi = 3.14;
int radius = 5;
int area;
area = subInc(radius,pi); /* 半径から面積を求める関数を呼び出す */
printf("Area = %d",area);
area = subroutine(radius,pi); /* 半径から面積を求める関数を呼び出す */
printf("Area = %d",area);
}
/*
* 半径から面積を計算(円周率を高精度にする)
* 引数:半径
* 戻り値:面積
*/
int subInc(int d, double pi) {
int a;
pi = 3.14159; /* 円周率の精度を上げる */
a = r * r * pi;
return a;
}
/*
* 半径から面積を計算
* 引数:半径
* 戻り値:面積
*/
int subroutine(int r, double pi) {
int a;
a = r * r * pi;
return a;
}
ルーチンを手続き化する関数を機能単位にまとめて入出力を絞りこみ、機能を独立して実現可能に設計したもの。
内部コードをブラックボックス*化することができ、モジュールの組み合わせによりプログラミングが可能になる。
モジュール同士の依存性の度合いを示す。一般的に結合度が低い(疎結合)であるほどモジュール設計としては優れており、結合度が高い(密結合)ほど使用性や保守性が低下する。
疎結合 | データ結合 | モジュールで必要なデータのみをインターフェースとする |
↑ (低) 結合度 (高) ↓ |
スタンプ結合 | グローバル変数でない同じデータ構造をインターフェースを介して共有する |
制御結合 | モジュールの動作を決定する情報を引数で渡す | |
外部結合 | パブリック変数を使用し、モジュール間でデータを共有する | |
共通結合 | 共通のメモリ領域を共有する | |
密結合 | 内容結合 | 他のモジュールの内容を直接参照する場合やモジュールの一部を共有する |
モジュール内での機能単位での独立性を示す。一般的に強度が高い(機能単位で独立している)ほどモジュール設計としては優れており、強度が低い(複数の機能が混在している)ほど使用性や保守性が低下する。
単一機能 | 機能的強度 | 1つの固有の機能のみを持つ |
↑ (高) 強度 (低) ↓ |
情報的強度 | 同じ構造のデータを扱う複数の機能をもつ |
連絡的強度 | 複数の機能が順番に後続の機能に影響を与える形で並んでいる | |
手段的強度 | 複数の機能が順番に後続の機能に影響を与えない形で並んでいる | |
時間的強度 | 初期設定など特定のタイミングで実行されて他の機能に影響を与える機能を持つ | |
論理的強度 | 関係のある複数の機能をひとつのモジュールにもつ | |
複数機能 | 暗号的強度 | 関係のない複数の機能をひとつのモジュールにもつ |
プログラムの動作を機能単位ではなく人間から見た利用対象単位(オブジェクト)で定義して、個々のオブジェクト間のメッセージのやり取りによる相互作用でプログラミングをおこなう概念。
カプセル化とはオブジェクトの内部情報を隠蔽し、オブジェクトがもつデータへのアクセスや操作(メソッド)をメッセージを通じてのみ行うという概念。内部情報を隠蔽することにより、O⁄Rインピーダンスミスマッチ*によるオブジェクトの利用者の混乱を避け、オブジェクトへのインターフェースをメッセージに一本化する。
ポリモーフィズム(多様性)とはオブジェクト指向においてオブジェクトごとにメッセージを用意するのではなく、同じメッセージに対して各オブジェクトがそれぞれの仕様に合わせた結果を出力する概念。これを実現するためには各オブジェクトが共通のメッセージをもち、この共通のメッセージを各々のオブジェクトがオーバライド(上書き)する必要がある。
各オブジェクトが共通のメッセージとメッセージが必要とするデータを持つためには、各オブジェクト共通の型(クラス)が必要になってくる。さらにそのクラスに多様性を持たせるには元のクラスの特性を保持しつつもそれぞれの特性を加えた別のクラスが必要になってくる。ポリフォーリズムの実現においてこの共通のメッセージを提供するクラスを「基底クラス(親クラス、スーパークラス)」と呼び、各オブジェクトそれぞれの特性を提供するクラスを「派生クラス(子クラス、サブクラス)」と呼ぶ。派生クラスが基底クラスの特性を受け継ぐことを「継承」という。
メモリ内でスタック構造に従って直接的に格納されているデータ。
メモリ内でヒープ構造に従って間接的に格納されているデータ。
実値型のデータを格納している領域。FILOのデータ構造に従ってメモリ上の領域に順番にデータが格納されている。プログラムが機械語に翻訳されるタイミングでメモリ領域が割り当てられる。固定長であり、アクセス速度は速い。
参照型のデータを格納している領域。データはメモリ上の領域にランダムに格納されている。そのため、格納位置を別途管理する必要がある。この格納位置はスタック領域で管理されている。プログラムが実行されるタイミングでメモリ領域が割り当てられる。可変長であり、アクセス速度は遅い。