Presentation is loading. Please wait.

Presentation is loading. Please wait.

情報処理Ⅱ 2007年12月10日(月).

Similar presentations


Presentation on theme: "情報処理Ⅱ 2007年12月10日(月)."— Presentation transcript:

1 情報処理Ⅱ 2007年12月10日(月)

2 自分の思う通りに,適切な形で,プログラムとして表現する.
授業の進め方 構造体 その他の型 2年以降で さらに学習・習熟 プリプロセッサ 指令 ライブラリ関数 ファイル入出力 自分の思う通りに,適切な形で,プログラムとして表現する. 配列・文字列 ポインタ 関数 変数の 有効範囲 識別子 算術型 再帰呼び出し 制御文 演算子 プログラムの作成・ コンパイル・実行

3 本日学ぶこと いくつかの型 なぜ「型」にこだわるか? 以下を読む上での注意 typedef 列挙型(enum型) 構造体
処理対象のデータを効果的・効率的に取り扱える 既存の機能をもとに,便利な機能を創れる 以下を読む上での注意 この色とこの色は型名を表す. この色は変数名を表す. プログラムを書きやすく 読みやすくする…定性的なメリット 実行時のコスト(メモリ使用量など)を見積もることができ,そこからプログラムの改善が期待できる…定量的なメリット リpp

4 typedef 独自に型(type)を定義(define)する. 例 構造体の型名定義によく用いられる.
ただし,メモリに割り当てるわけでないので,「宣言」である. typedef signed char schar; schar c; ⇒ signed char c; と同じ typedef unsigned char uchar; uchar c, *p; ⇒ unsigned char c, *p; と同じ typedef char *String; String s, t; ⇒ char *s, *t; と同じ typedef char c5[5]; c5 x, y, z; ⇒ char x[5], y[5], z[5]; と同じ 構造体の型名定義によく用いられる. リp.107, pp

5 typedefの考え方 変数の定義 型の定義 char c5[5]; は,変数c5を定義し,その型はchar [5]型とする.

6 列挙型(enumeration)とは 「ラベル」を格納・参照・比較したいときに使う. 構文: enum タグ名 { 列挙子並び };
変数に格納される具体的な値には関心がない. 実際には,ラベルに整数値が割り当てられる.これを積極的に活用することもある. 構文: enum タグ名 { 列挙子並び }; 「enum タグ名」型が定義される. 列挙子は「,」で区切る. リpp.65-66, p.138

7 列挙型の使用例 1 enum Boolean {FALSE, TRUE}; enum Boolean p = TRUE, q = FALSE, r = p||q; enum month {   Jan = 1, Feb, Mar, ..., Dec, MONTH_END } mloop; int rain[100][MONTH_END]; for (mloop = Jan; mloop < MONTH_END; mloop++) {   rain[7][mloop] = ...; } 13 型と変数を同時に定義 年月単位の降水量を格納する

8 汎整数型 汎整数型(integral type)に含まれるもの 列挙型は,計算時にはint型とみなされる.
整数型(char,int,long など) 列挙型 size_t型(sizeof演算子の評価値など.unsigned intまたはunsigned longと同一のことが多い.) 列挙型は,計算時にはint型とみなされる. ただし,利用は代入,比較,範囲内の増分・減分にとどめておく. リp.64

9 構造体(structure) 複数のオブジェクトを取りまとめて一つのオブジェクトとして扱うための機構 構造体で表現するとよいもの
(2次元,3次元などの)座標上の点 複素数 行列(行数と列数と各成分) 所持金 学生情報 (x,y) 500 50 100 10 学生番号:0001 氏名:和大太郎 情報処理Ⅰの成績:80 情報処理Ⅱの成績:75 修得単位数: 52 入p.242 リp.366

10 構造体宣言の例(1) 構文: struct タグ名 { メンバ宣言子並び }; 例 「struct タグ名」型が定義される.
struct point { double x; double y; }; struct point p = {1, -1}; セミコロンを忘れない ように この x と y を, point構造体の メンバという. x = 1 y = -1 p: 配列と同じ書式で 初期化可能 リpp , pp

11 構造体宣言の例(2) 構造体宣言と変数定義を一つの文で 構造体宣言と型定義を一つの文で
struct point { double x; double y; } p; 構造体宣言と型定義を一つの文で typedef struct Point { double x, y; } point; point p; 「,」を用いて メンバを一括 宣言してよい 構造体宣言と型定義とを同時に行った場合, struct Point型とpoint型とで相互に参照・代入してよい. C++では,「構造体のタグ名」と「型名」が重複するとエラーとなる. リp.367の例でも,別にしている. typedefは,「structとタイプするのを減らす」ためではなく,「構造体であることを見えなくする」ために使用すべきである. struct Point型と point型が定義される 入p.242 リpp

12 構造体宣言の例(3) 無名構造体 struct { double x; double y; } p;
typedef struct { double x, y; } point; point p; 無名構造体として定義した変数は,そのメンバへのアクセスはできるが, 関数呼び出しの引数としては使用できない(どんな型か,コンパイラは分からない). typedef struct {略} point; と定義した場合,その型のオブジェクト同士では参照や代入ができるが, 前のページのstruct point型と相互に(構造体として)代入することは,できない.

13 構造体宣言の例(4) 行列(行数,列数とも10まで) 行列(成分はポインタ) struct matrix { row column
int row, column; double element[10][10]; }; 行列(成分はポインタ) double **element; row column element row column element 上の構造体について, rowとcolumnは,コンパイラが参照するためのラベルであると同時に, この構造体のオブジェクトを定義すると,それぞれの値を格納する領域もメモリ上に確保される. elementは,コンパイラが参照するためのラベルであるが,メモリ上には確保されない. elementが参照する二次元配列領域は,メモリ上に確保されるが,elementを介することなく, 直接各要素の値を獲得したり,書き換えたりすることはできない. 下の構造体について,行列の各要素は,構造体オブジェクトの外で確保することになる.

14 構造体宣言の例(5) 自己参照構造体 struct node { graph … label = 'A' label = 'Z' next
char label; struct node *next; }; struct node graph[100]; graph[0].label = 'A'; graph[0].next = graph + 1; graph[1].label = 'Z'; graph[1].next = NULL; graph label = 'A' label = 'Z' next next = NULL 自己参照構造体が定義できるのは, メンバnextの型が(自己参照する)構造体そのものではなくそのポインタだから. 専門用語を用いると,nextの型を決定する時点では「struct node」型が「不完全型」として利用可能となっていて, 型定義の「};」を終えたところで,「struct node」型は「構造体型」とみなされる. そもそも,どのようにメモリに構造体オブジェクトを作ればよいかを考えると, メンバが,自己参照する構造体そのものではまずい(その型が定義できて, 変数も確保できたとして,sizeof(変数)が計算できる?). ここで問題.無名構造体かつ自己参照構造体という型を作ることはできるか? リp.69, p.143, p.372, p.376

15 構造体の参照と代入(1) 前提 メンバへのアクセス方法
struct point { double x, y; }; struct point p, *pp = &p; メンバへのアクセス方法 構造体オブジェクトpのメンバxは p.x と書いて 参照・代入ができる. 構造体オブジェクトを指し示すポインタppについては,(*pp).x もしくは pp->x と書けばよい. . と -> は演算子であり,最上位の優先順位を持つ. x y p: pp × *pp.x 入p.243 リp.157, pp

16 構造体の参照と代入(2) 構造体オブジェクトの代入 構造体渡し
struct matrix a, b; (aを初期化) b = a; とすると,bにはaのコピーが格納される. 構造体の中に配列があっても,コピーされる. 構造体の中のポインタは,ポインタ値がコピーされる. 構造体渡し 関数の引数や戻り値の授受でも,構造体オブジェクトが代入(コピー)される. しかし,構造体はしばしばポインタで渡される(参照渡し). 関数処理で,構造体オブジェクトの中の値を変えたいとき 大きなサイズの構造体オブジェクトをスタックに置きたくないとき リp.163, p.358, pp.97-98

17 三角形の面積:仕様 2次元座標上の三角形の面積を求める. 構造体を用いる.
三点P(a, b), Q(c, d), O(0,0)からなる⊿PQOの面積は,|ad-bc|/2 で求められることを利用する. y O x

18 三角形の面積:構造体 2次元座標の点 三角形の3点 メンバと変数は,識別子が重複していてもよい. struct point {
double x, y; }; 三角形の3点 struct triangle { struct point p1, p2, p3; メンバと変数は,識別子が重複していてもよい. リp.103

19 三角形の面積:関数 struct triangle transform_triangle(struct triangle t);
三角形の3点を,メンバp3が原点になるように平行移動する. double calc_area(struct triangle t); 三角形の面積を求める. y y p1(1,3) p1(-3,1) p3(4,2) p3(0,0) O x O p2(5,0) x p2(1,-2)

20 構造体利用時の注意 構造体と配列の使い分け sizeof(構造体) 構造体とプログラミング してはいけないこと

21 構造体と配列の使い分け 配列 構造体 「配列を含む構造体」や「構造体の配列」もよく利用される. 同一の型の集まり 各要素に番号がついている
ループなどを使って順番に処理する 構造体 様々な型の集まり(ただし,同一の型の集まりでもよい) 各要素に付けられた名前を使ってアクセスする 「配列を含む構造体」や「構造体の配列」もよく利用される. 入p.244

22 sizeof(構造体) sizeof(構造体) は,構造体の各メンバのサイズの合計以上になる.
構造体オブジェクトの中で使用されない領域もあり得る.「パディング」または「穴」と呼ばれる. s: c i パディング struct s { char c; int i; }; sizeof(char) == 1 sizeof(int) == 4 でも sizeof(struct s) != 5 リp.373

23 構造体とプログラミング さまざまな種類の情報を持つ「実体」を一つのオブジェクトとして処理したいとき,
まず,「何に処理をしたいか?」を考える. 保持すべき情報を細分化し,それぞれをメンバとするような構造体を宣言する. 次に,「何の処理をしたいか?」を考える. 構造体を引数にとって処理する関数を定義する. 引数・戻り値ともに,型は構造体そのものにすべきか, 構造体のポインタにすべきか,そのつど検討する. 動作確認用に,構造体の中身を出力する関数も.

24 してはいけないこと × 関数内のauto変数を指し示すポインタを,戻り値とする.
struct point *create_point(int x, int y) {   struct point p = {x, y}; return &p; } コンパイルエラーにはならないが,実行時に支障をきたす. 関数処理が終わると,pの領域が破棄される ⇒ *(&p)が不定! pをstatic変数とするか,mallocで実行時に領域を確保してそのポインタを返せば,問題を回避できる. リpp

25 独自の型はどこで定義する? 一般には,グローバル区間で定義し,複数の関数間で利用できるようにする. ブロックの中で定義してもよい.
#include文の後ろ,関数プロトタイプの前に書く. ブロックの中で定義してもよい. 有効範囲は,そのブロックの終わりまで.

26 まとめ 独自の型(typedef,列挙型,構造体)を定義することで,変数に持たせる意味がより明確になる.
構造体により,複数のデータからなるオブジェクトを創ることができる. 構造体を対象とする関数を定義するとき,(引数・戻り値の)型は構造体そのものにすべきか,構造体のポインタにすべきか,そのつど検討する.

27 今後の予定 2007年12月17日(月):第11回授業 2008年1月10日(木):休講 2008年1月17日(木):第2回レポート提出期限
次回授業終了後すぐ,授業Webページにて,第2回レポート課題を掲示します. 2008年1月10日(木):休講 2008年1月17日(木):第2回レポート提出期限 2008年1月21日(月):第12回授業 2008年1月28日(月):第13回授業 2008年1月30日(水):第14回授業


Download ppt "情報処理Ⅱ 2007年12月10日(月)."

Similar presentations


Ads by Google