270 likes | 362 Views
情報処理 Ⅱ. 2007年12月10日(月). 授業の進め方. その他の型. 構造体. 2年以降で さらに学習・習熟. プリプロセッサ 指令. ライブラリ関数. ファイル入出力. 自分の思う通りに,適切な形で,プログラムとして表現する.. 配列・文字列. ポインタ. 関数. 変数の 有効範囲. 算術型. 識別子. 再帰呼び出し. 制御文. 演算子. プログラムの作成・ コンパイル・実行. プログラムを書きやすく 読みやすくする … 定性的 なメリット.
E N D
情報処理Ⅱ 2007年12月10日(月)
授業の進め方 その他の型 構造体 2年以降でさらに学習・習熟 プリプロセッサ指令 ライブラリ関数 ファイル入出力 自分の思う通りに,適切な形で,プログラムとして表現する. 配列・文字列 ポインタ 関数 変数の有効範囲 算術型 識別子 再帰呼び出し 制御文 演算子 プログラムの作成・コンパイル・実行
プログラムを書きやすく 読みやすくする…定性的なメリット 実行時のコスト(メモリ使用量など)を見積もることができ,そこからプログラムの改善が期待できる…定量的なメリット 本日学ぶこと • いくつかの型 • typedef • 列挙型(enum型) • 構造体 • なぜ「型」にこだわるか? • 処理対象のデータを効果的・効率的に取り扱える • 既存の機能をもとに,便利な機能を創れる • 以下を読む上での注意 • この色とこの色は型名を表す. • この色は変数名を表す. リpp.108-109
typedef • 独自に型(type)を定義(define)する. • ただし,メモリに割り当てるわけでないので,「宣言」である. • 例 • typedef signed charschar;scharc; ⇒ signed char c; と同じ • typedef unsigned charuchar;ucharc, *p; ⇒ unsigned char c, *p; と同じ • typedef char *String;Strings, t; ⇒ char *s, *t; と同じ • typedef charc5[5];c5x, y, z; ⇒ char x[5], y[5], z[5]; と同じ • 構造体の型名定義によく用いられる. リp.107, pp.142-145
typedefの考え方 • 変数の定義 • charc5[5];は,変数c5を定義し,その型はchar [5]型とする. • 型の定義 • typedef charc5[5]; は,c5型を定義し,その型はchar [5]型と同一とみなす.
列挙型(enumeration)とは • 「ラベル」を格納・参照・比較したいときに使う. • 変数に格納される具体的な値には関心がない. • 実際には,ラベルに整数値が割り当てられる.これを積極的に活用することもある. • 構文: enum タグ名 { 列挙子並び }; • 「enum タグ名」型が定義される. • 列挙子は「,」で区切る. リpp.65-66, p.138
列挙型の使用例 0 1 • 例 • enum Boolean {FALSE, TRUE};enum Booleanp = TRUE, q = FALSE, r = p||q; • enum month {Jan = 1, Feb, Mar, ..., Dec, MONTH_END} mloop;intrain[100][MONTH_END];for (mloop = Jan; mloop < MONTH_END; mloop++) {rain[7][mloop] = ...;} 13 型と変数を同時に定義 年月単位の降水量を格納する
汎整数型 • 汎整数型(integral type)に含まれるもの • 整数型(char,int,long など) • 列挙型 • size_t型(sizeof演算子の評価値など.unsigned intまたはunsigned longと同一のことが多い.) • 列挙型は,計算時にはint型とみなされる. • ただし,利用は代入,比較,範囲内の増分・減分にとどめておく. リp.64
(x,y) 500 50 10 100 100 100 構造体(structure) • 複数のオブジェクトを取りまとめて一つのオブジェクトとして扱うための機構 • 構造体で表現するとよいもの • (2次元,3次元などの)座標上の点 • 複素数 • 行列(行数と列数と各成分) • 所持金 • 学生情報 学生番号:0001 氏名:和大太郎 情報処理Ⅰの成績:80 情報処理Ⅱの成績:75 修得単位数: 52 入p.242 リp.366
p: x = 1 y = -1 構造体宣言の例(1) • 構文: struct タグ名 { メンバ宣言子並び }; • 「struct タグ名」型が定義される. • 例 • struct point {double x;double y;};struct pointp= {1, -1}; セミコロンを忘れない ように この x と y を, point構造体の メンバという. 配列と同じ書式で初期化可能 リpp.366-367, pp.205-206
構造体宣言の例(2) • 構造体宣言と変数定義を一つの文で • struct point {double x;double y;} p; • 構造体宣言と型定義を一つの文で • typedef struct Point {double x, y;} point;pointp; 「,」を用いて メンバを一括 宣言してよい struct Point型と point型が定義される 入p.242 リpp.367-368
構造体宣言の例(3) • 無名構造体 • struct {double x;double y;} p; • typedef struct{double x, y;} point;pointp;
row column element … 構造体宣言の例(4) • 行列(行数,列数とも10まで) • struct matrix { • int row, column; • double element[10][10]; • }; • 行列(成分はポインタ) • struct matrix { • int row, column; • double **element; • }; row column element
構造体宣言の例(5) • 自己参照構造体 • struct node { • char label; • struct node *next; • }; • struct nodegraph[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 リp.69, p.143, p.372, p.376
p: x y 構造体の参照と代入(1) • 前提 • struct point {double x, y;};struct pointp, *pp = &p; • メンバへのアクセス方法 • 構造体オブジェクトpのメンバxは p.xと書いて参照・代入ができる. • 構造体オブジェクトを指し示すポインタppについては,(*pp).xもしくは pp->xと書けばよい. • . と -> は演算子であり,最上位の優先順位を持つ. pp × *pp.x 入p.243 リp.157, pp.367-368
構造体の参照と代入(2) • 構造体オブジェクトの代入 • struct matrixa, b;(aを初期化) b = a;とすると,bにはaのコピーが格納される. • 構造体の中に配列があっても,コピーされる. • 構造体の中のポインタは,ポインタ値がコピーされる. • 構造体渡し • 関数の引数や戻り値の授受でも,構造体オブジェクトが代入(コピー)される. • しかし,構造体はしばしばポインタで渡される(参照渡し). • 関数処理で,構造体オブジェクトの中の値を変えたいとき • 大きなサイズの構造体オブジェクトをスタックに置きたくないとき リp.163, p.358, pp.97-98
三角形の面積:仕様 • 2次元座標上の三角形の面積を求める. • 構造体を用いる. • 三点P(a, b), Q(c, d), O(0,0)からなる⊿PQOの面積は,|ad-bc|/2 で求められることを利用する. y O x
三角形の面積:構造体 • 2次元座標の点 struct point { double x, y; }; • 三角形の3点 struct triangle { struct point p1, p2, p3; }; • メンバと変数は,識別子が重複していてもよい. リp.103
三角形の面積:関数 • struct triangletransform_triangle(struct trianglet); • 三角形の3点を,メンバp3が原点になるように平行移動する. • doublecalc_area(struct trianglet); • 三角形の面積を求める. y y p1(1,3) p1(-3,1) p3(4,2) p3(0,0) O x O p2(5,0) x p2(1,-2)
構造体利用時の注意 • 構造体と配列の使い分け • sizeof(構造体) • 構造体とプログラミング • してはいけないこと
構造体と配列の使い分け • 配列 • 同一の型の集まり • 各要素に番号がついている • ループなどを使って順番に処理する • 構造体 • 様々な型の集まり(ただし,同一の型の集まりでもよい) • 各要素に付けられた名前を使ってアクセスする • 「配列を含む構造体」や「構造体の配列」もよく利用される. 入p.244
s: c パディング i sizeof(構造体) • sizeof(構造体) は,構造体の各メンバのサイズの合計以上になる. • 構造体オブジェクトの中で使用されない領域もあり得る.「パディング」または「穴」と呼ばれる. struct s { char c; int i; }; sizeof(char) == 1 sizeof(int) == 4 でも sizeof(struct s) != 5 リp.373
構造体とプログラミング • さまざまな種類の情報を持つ「実体」を一つのオブジェクトとして処理したいとき, • まず,「何に処理をしたいか?」を考える. • 保持すべき情報を細分化し,それぞれをメンバとするような構造体を宣言する. • 次に,「何の処理をしたいか?」を考える. • 構造体を引数にとって処理する関数を定義する. • 引数・戻り値ともに,型は構造体そのものにすべきか,構造体のポインタにすべきか,そのつど検討する. • 動作確認用に,構造体の中身を出力する関数も.
してはいけないこと • ×関数内のauto変数を指し示すポインタを,戻り値とする. • struct point *create_point(int x, int y){struct pointp = {x, y}; return &p;} • コンパイルエラーにはならないが,実行時に支障をきたす. • 関数処理が終わると,pの領域が破棄される⇒ *(&p)が不定! • pをstatic変数とするか,mallocで実行時に領域を確保してそのポインタを返せば,問題を回避できる. リpp.118-119
独自の型はどこで定義する? • 一般には,グローバル区間で定義し,複数の関数間で利用できるようにする. • #include文の後ろ,関数プロトタイプの前に書く. • ブロックの中で定義してもよい. • 有効範囲は,そのブロックの終わりまで.
まとめ • 独自の型(typedef,列挙型,構造体)を定義することで,変数に持たせる意味がより明確になる. • 構造体により,複数のデータからなるオブジェクトを創ることができる. • 構造体を対象とする関数を定義するとき,(引数・戻り値の)型は構造体そのものにすべきか,構造体のポインタにすべきか,そのつど検討する.
今後の予定 • 2007年12月17日(月):第11回授業 • 次回授業終了後すぐ,授業Webページにて,第2回レポート課題を掲示します. • 2008年1月10日(木):休講 • 2008年1月17日(木):第2回レポート提出期限 • 2008年1月21日(月):第12回授業 • 2008年1月28日(月):第13回授業 • 2008年1月30日(水):第14回授業