前回の内容
データ構造の必要性
プログラムを作成
命令を並べて、目的とする機能を実現する
三つの制御構造
順接 : 命令を順に実行する
条件分岐 : 条件によって、複数の命令を切りかえる
繰り返し : 条件が成立する限り、命令を繰り返す
=>
基本的な命令を組み合わせる事により、
任意の機能が実現できる
=>
C 言語で、これらをどのように表現するか ?
順接 => 並べるだけ
条件分岐 : if 構文 / switch 構文
繰り返し : 再帰構造 / while / for 構文
分割統治
目的を、副目的に分割する
プログラムを作成する目的
プログラムを使って、現実の機能を実現したい
現実とコンピュータの対応関係が必要
現実の対象が複雑
コンピュータの扱うデータも複雑
データを設計する <=> プログラム構造の設計
C 言語 : 手続き型言語
=> 命令の組み合わせ(手続き)でプログラム
<=> 対象となる(現実のモノに対応した)データの組み合わせ
=> オブジェクト指向
対象を記述すれば.. (自然に..) 対象が相互作用して、
目的の機能を実現する(シミュレーションの発想)
=> データ構造
データ構造 (1)
コーディング : 数値で情報を扱う原理
(現実の)情報と(コンピュータの中の)数値の対応関係
例: ASCII Code
現実の「文字」 <=> コンピュータの「整数値」
'A'=>'a' <=> +32
=> 情報処理が、計算で(間接的に..)表現可能になる
コードからデータへ( => オブジェクト )
プログラム = データ構造 + アルゴリズム
データ構造を作る
複数の「単純なデータ」の組み合せ
で「複雑なデータ」を作る仕組み
構造体 : 直積空間の構成
n 個の(単純な/基本となる)データの組み合わせで、
複雑なデータを表現する手段
=> 直積空間 ( A, B => A x B = { | a \in A, b \in B } )
構文:
a \in int, b \in double => struct s = int x dobule
struct s {
int a;
double b;
};
typedef : 型に名前を付ける仕組み
typedef struct s {
int a;
double b;
} S;
struct s に S という名前を付ける
=> 以下、S と書けば、struct s と同じ意味
要素の取り出し
S = int x double = { | a \in int, b \in double }
s \in S
s <-> ( 整数値と浮動小数点の組 )
s.a -> s を構成する要素の整数の部分
s.b -> s を構成する要素の浮動小数点の部分
代入
S s; S 型の変数
S t;
s = t; S 型の変数での代入ができる
=> 代入ができる
=> 関数の引数や、返り値に S が使える
# できない事
# その型の定数(表現):リテラルが表現できない
S s = <1,0.1>; <= このような表現ができない
==
配列
同じ型のデータが多数並んだ物を表現する仕組
cf. 構造体: 異なる型が(少数)並んだ物を表現する
# 配列の方が「効率が良い」事が多い
# <= 繰り返しと相性の良さ
# 配列と同じ扱いで、「ポインタ型」の扱いができる
# => 配列が「多用」されている
例: double a0,a1,a2 -> double a[3] /* a[0], a[1], a[2] */
配列名 : データの並びが入る変数の代表名
添字 「'[' + 整数値 ']'」を付けて、要素が参照できる
配列の宣言の時、配列の要素の個数 N を指定して
型 配列名[N];
=> N 個の変数が宣言
型 配列名[0], 配列名[1], .., 配列名[N-1];
C 言語では添え字は 0 から始まる
配列の宣言
配列を利用する(宣言する)場合は、「配列名[サイズ]」の形にする
サイズ個数の変数がまとめて用意される
参照する場合は 0 〜 サイズ-1 まで
例:
int ary[10];
とすると
ary[0] 〜 ary[9] = ary[10-1]
が使える
<<重要>>
配列の要素を参照する場合は、
配列名[要素番号]
の形で、参照するが、
要素番号の所には、「整数『式』」が書ける
『式』には、変数を含める事ができる
同じ「表現」でも「変数の値」変更する事により、
異なる「動作」をさせる事ができる
!! cf. 関数の引数
!! a1 は 「a『1』」という具体的な数値(1)を指定する
!! a[1]は「i=1; a[i]」という間接的に(変数を経由して)指定できる
!! => 柔軟性が出てくる
!! 配列 vs 関数
!! a[x], f(x) : ともに変数を利用して、(同じ表現で)異なる意味になる
!! 配列 : 変数なので、予め代入した値が得られる
!! => 低機能
!! 関数 : 命令ががけるので、高度な計算結果を返す事ができる
!! => 高機能
!! => 配列の機能を関数で実現する事も可能
!! 配列は変数なので、「代入」が可能
!! 関数は、代入文の右にしかかけない
!! 配列は、代入可能なので、代入文の左にもかける
!! # 「変数」は「『左辺値』を持つ」
配列プログラミング (集合操作)
配列 vs 集合
配列は、複数の同じ型の変数(配列の要素)をまとめたもの
集合の要素は、値そのもの
例: 二次元ベクトルの要素
(1,2) : 値の組み合わせ
配列(データ構造/構造体も同様..)
値を保存できる「変数」を用意し、
その変数に「値を保持させる」事により、
その変数で、値(集合の要素)を差し示す事ができる
cf. 基本型の場合は、変数を利用せずに、値が表現できる(リテラル)
例:
整数値の「1」は、直接 C 言語で「1」と表現できる
文字の「A」は、直接 C 言語で「'A'」と表現できる
!! 「『集合』の『要素』」は、『集合』に含まれる『値』の事
!! 例 : A = { 6 の約数 } = { 1, 2, 3, 6 }
!! A の要素は 1, 2, 3, 6 の四つ
!!「『配列』の『要素』」は、『配列』の一部である個々の変数の事
!! 例 : int a[4] => 配列 a の要素 a[0], a[1], a[2], a[3]
!!「『構造体』の『要素』」は、『構造体』の一部である個々の変数の事
!! 例 : struct { int x; int y } s;
!! 構造体 s の要素 s.x,s.y
配列の個々の要素は、同じ型の値を保持する変数
一つの配列(が保持する値の集まり) は、その型の「集合」を表す
!! 配列のサイズと同じ(あるいはそれ以下)の要素からなる
!! 例 int a[3];
!! a <-> { 1, 2, 3 }
!! <-> { 123, 456, 789 }
!! !! 集合のサイズは、可変
!! !! => 配列サイズは、最初に固定する必要がある
!! !! # 後で、ポインター型の所で、可変な配列(のようなもの)が利用できる
集合操作
{1, 2, 3} -> {2, 4, 6} # すべての要素を 2 倍
{1, 2, 3} -> {4, 5, 5} # すべての要素に 3 を加える
配列の要素(複数)への操作を「繰返し」で表現する
「『集合全体』への操作」が、「個々の要素の操作の『繰返し』」になる
<注意>
配列は、集合のように要素数が変化したりはしない
配列の異る要素(変数)が同じ値を持つ事もある