情報処理Ⅱ 2006年12月15日(金) 前回の補足1 ライブラリ関数の分類 標準ライブラリ関数(標準関数,ANSI準拠の関数) • この科目で使用するのは,この範囲だけ POSIX準拠の関数 • 情報ネットワーク演習で使用する その他(サードパーティライブラリ) • OpenGL(ビジュアル情報演習で使用する) 関数・定数・独自型などをまとめて,他のプログラムから利用 できるよう部品化したものを「ライブラリ」という. ANSI: American National Standard Institute POSIX: Portable Operating System Interface for UNIX 2 前回の補足2 複雑な式も,木構造(構文木) で表現できる. コンパイラは,ソースコード(文 字列)をこの種の木構造で表 現し,それから計算機が実行 できるコード(オブジェクトコー ド)に変換する.処理の中で, 再帰呼び出しが用いられるこ とがある. 「s != NULL && *s != '\0'」の 構文木 && != s != NULL * '\0' s 3 授業の進め方 構造体 プリプロセッサ 指令 その他の型 ライブラリ関数 自分の思う通りに,適切な形で,プ ログラムとして表現する. 識別子 算術型 制御文 演算子 2年以降で さらに学習・習熟 ファイル入出力 配列・文字列 ポインタ 関数 変数の 有効範囲 再帰呼び出し プログラムの作成・ コンパイル・実行 4 本日学ぶこと いくつかの型 なぜ「型」にこだわるか? typedef 列挙型(enum型) 構造体 プログラムを書きやすく 読みやすくする…定性的 なメリット 実行時のコスト(メモリ使用量な ど)を見積もることができ,そこか らプログラムの改善が期待できる …定量的なメリット 処理対象のデータを効果的・効率的に取り扱える 既存の機能をもとに,便利な機能を創れる 以下を読む上での注意 この色とこの色は型名を表す. この色は変数名を表す. 5 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]; と同じ 構造体の型名定義によく用いられる. 6 typedefの考え方 変数の定義 char c5[5]; は,変数c5を定義し,その型はchar [5]型 とする. 型の定義 typedef char c5[5]; は,c5型を定義し,その型は char [5]型と同一とみなす. 7 列挙型(enumeration)とは 「ラベル」を格納・参照・比較したいときに使う. 変数に格納される具体的な値には関心がない. 実際には,ラベルに整数値が割り当てられる.これを積極的に 活用することもある. 構文: enum タグ名 { 列挙子並び }; 「enum タグ名」型が定義される. 列挙子は「,」で区切る. 8 列挙型の使用例 例 0 1 enum Boolean {FALSE, TRUE}; enum Boolean p = TRUE, q = FALSE, r = p||q; 13 enum month { Jan = 1, Feb, Mar, ..., Dec, MONTH_END } mloop; 型と変数を同時に定義 int rain[100][MONTH_END]; for (mloop = Jan; mloop < MONTH_END; mloop++) { rain[6][mloop] = ...; } 年月単位の降水量を格納する 9 汎整数型 整数型(char,int,long など)と列挙型を合わせて, 汎整数型(integral type)という. 列挙型は,計算時にはint型とみなされる. ただし,利用は代入,比較,範囲内の増分・減分にとどめておく. 10 構造体(structure) 複数のオブジェクトを取りまとめて一つのオブジェクトとして 扱うための機構 構造体で表現するとよいもの (x,y) (2次元,3次元などの)座標上の点 複素数 行列(行数と列数と各成分) 所持金 学生情報 500 100 100 100 50 10 学生番号:0001 氏名:あいうえお 情処Ⅰの点数:80 情処Ⅱの点数:75 修得単位数: 52 11 構造体の構文と定義の例(1) 構文: struct タグ名 { メンバ宣言子並び }; 「struct タグ名」型が定義される. 例 struct point { この x と y を, double x; point構造体の double y; メンバという. }; struct point p = {1, -1}; セミコロンを忘れない ように p: x=1 y = -1 配列と同じ書式で 初期化可能 12 構造体の定義の例(2) 構造体宣言と変数定義を一つの文で struct point { double x; double y; } p; 構造体宣言と型定義を一つの文で typedef struct point { double x, y; } point; point p; struct point型と point型が定義される 13 構造体の定義の例(3) 無名構造体 struct { double x; double y; } p; typedef struct { double x, y; } point; point p; 14 構造体の定義の例(4) 行列(行数,列数とも10まで) struct matrix { int row, column; double element[10][10]; }; • • row column element … 行列(成分はポインタ) struct matrix { int row, column; double **element; }; row • column • element 15 構造体の定義の例(5) 自己参照構造体 struct node { graph int value; struct node *next; value = 1 }; next struct node graph[100]; graph[0].value = 1; graph[0].next = graph + 1; graph[1].value = 99; graph[1].next = NULL; • • value = 99 … next = NULL 16 構造体の参照と代入(1) 前提 struct point { double x, y; }; struct point p, *pp = &p; メンバへのアクセス方法 p: pp x y × *pp.x 構造体オブジェクトpのメンバxは p.x と書いて 参照・代入ができる. 構造体オブジェクトのポインタppについては,(*pp).x もしく は pp->x と書けばよい. • . と -> は演算子であり,最上位の優先順位を持つ. 17 構造体の参照と代入(2) 構造体オブジェクトの代入 struct matrix a, b; (aを初期化) b = a; とすると, bにはaのコピーが格納される. 構造体の中に配列があっても,コピーされる. 構造体の中のポインタは,ポインタ値がコピーされる. 構造体渡し 関数の引数や戻り値の授受でも,構造体オブジェクトが代入 (コピー)される. しかし,構造体はしばしばポインタで渡される(参照渡し). • 関数処理で,構造体オブジェクトの中の値を変えたいとき • 大きなサイズの構造体オブジェクトをスタックに置きたくない とき 18 両替問題の仕様(1) 両替機の両替部分をシミュレート(模擬)する. 入金に対して,どの紙幣・貨幣を何枚出せばいいかを出力す る. 「崩す」(一万円札を千円札10枚にするなど)のは考えない. 金額に関する情報 一万円,五千円,千円の各紙幣(bill)の枚数 500円,100円,50円,10円,5円,1円の各硬貨(coin)の 枚数 合計金額(amount) ⇒ 構造体のメンバ? 100 100 100 100 50 10 10 10 5 5 5 5 500 19 両替問題の考え方 知りたい情報,行いたい操作 紙幣・貨幣がそれぞれ何枚ある(入金された,出金しないとい けない)かを知る 合計金額を求める 両替する • 両替前の「紙幣・貨幣の枚数の情報」に対して, 両替後の「紙幣・貨幣の枚数の情報」を求める 20 両替問題のプログラミング(1) 金銭構造体 struct money { int bill_10000, bill_5000, bill_1000; int coin_500, coin_100, coin_50, coin_10, coin_5, coin_1; }; • • 21 両替問題のプログラミング(2) 定義した関数 void print_money(struct money *moneyp); • 枚数と総額を出力する • 構造体のポインタを引数にとる int calc_amount(struct money *moneyp); • 総額を求める • 構造体のポインタを引数にとる struct money change_money(struct money money_in); • 両替する • 構造体オブジェクトを引数にとり,構造体オブジェクトを返す 22 その他の話題 構造体と配列の使い分け sizeof(構造体) 構造体とプログラミング してはいけないこと 独自の型はどこで定義する? 23 構造体と配列の使い分け 配列 構造体 同一の型の集まり 各要素に番号がついている ループなどを使って順番に処理する 様々な型の集まり(ただし,同一の型の集まりでもよい) 各要素に付けられた名前を使ってアクセスする 「配列を含む構造体」や「構造体の配列」もよく利用される. 24 sizeof(構造体) sizeof(構造体) は,構造体の各メンバのサイズの合計 以上になる. 構造体オブジェクトの中で使用されない領域もあり得る.「パ ディング」という. s: c struct s { char c; int i; }; パディング i sizeof(char) == 1 sizeof(int) == 4 でも sizeof(struct s) != 5 25 構造体とプログラミング さまざまな種類の情報を持つ「実体」を一つのオブジェクトと して処理したいとき, まず,「何に処理をしたいか?」を考える. • そのオブジェクトの型を構造体で定義する. • 座標上の点,学生情報,ノード(節点),など. 次に,「何の処理をしたいか?」を考える. • 構造体を引数にとって処理する関数を定義する. • 引数・戻り値ともに,型は構造体そのものにすべきか, 構造体のポインタにすべきか,そのつど検討する. 26 してはいけないこと × 関数内のauto変数を指し示すポインタを,戻り値とする. struct money *create_money(void) { struct pocket money = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; return &money; } コンパイルエラーにはならないが,実行時に支障をきたす. 関数処理が終わると,moneyの領域が破棄される ⇒ *(&money)が不定! 27 独自の型はどこで定義する? 一般には,グローバル区間で定義し,複数の関数間で利用 できるようにする. #include文の後,関数プロトタイプの前に書く. ブロックの中で定義してもよい. 有効範囲は,そのブロックの終わりまで. 28 まとめ 独自の型(typedef,列挙型,構造体)を定義することで, 変数に持たせる意味がより明確になる. 構造体により,複数のデータからなる「システム」を創ること ができる. 構造体を対象とする関数を定義するとき, (引数・戻り値の) 型は構造体そのものにすべきか,構造体のポインタにすべ きか,そのつど検討する. 29 予告 次回授業終了後すぐ,授業Webページにて,第2回レポート 課題を掲示します. 30
© Copyright 2024 ExpyDoc