情報処理Ⅱ 2006年12月15日(金).

Slides:



Advertisements
Similar presentations
情報処理Ⅱ 第7回:2003年12月2日(火). 問題(授業がつまらない人のため に) ぷよ連結問題 前提 : フィールドを2次元 配列で定義し,各マスの 「ぷよ」を int 型の値で表現 する. ある地点を入力に取り,そ れと連結する「ぷよ」の個 数を求めよ. 消去できる「ぷよ」 (N 個以上 連結するぷよと,それに隣接する特.
Advertisements

アルゴリズムとデータ構造 第2回 線形リスト(復習).
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第3回 配列(1) 情報・知能工学系 山本一公
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
情報処理Ⅱ 第10回 2004年12月14日(火).
プログラミング言語としてのR 情報知能学科 白井 英俊.
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
第13回構造体.
ファーストイヤー・セミナーⅡ 第8回 データの入力.
データ構造とアルゴリズム 第10回 mallocとfree
第12回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとプログラミング (Algorithms and Programming)
情報処理Ⅱ 2007年12月17日(月).
プログラミング言語論 第6回 型 情報工学科 篠埜 功.
情報処理Ⅱ 2005年12月9日(金).
アルゴリズムとデータ構造 2011年6月13日
構造体.
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
情報処理Ⅱ 2007年12月10日(月).
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
構造体 構造体, 構造体とポインタの組み合わせ,.
第10回 プログラミングⅡ 第10回
情報処理Ⅱ 2007年11月5日(月).
情報処理Ⅱ 第2回 2007年10月15日(月).
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング演習I 2003年5月7日(第4回) 木村巌.
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
第11回 プログラミングⅡ 第11回
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
フロントエンドとバックエンドのインターフェース
情報処理Ⅱ 第2回:2003年10月14日(火).
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
構造体と共用体.
データ構造とアルゴリズム 第11回 リスト構造(1)
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
ポインタとポインタを用いた関数定義.
アルゴリズムとデータ構造 2012年6月11日
情報処理Ⅱ 第2回 2005年10月14日(金).
情報処理Ⅱ 第2回 2006年10月13日(金).
アルゴリズムとデータ構造1 2009年6月15日
第5回 プログラミングⅡ 第5回
情報処理Ⅱ 第7回 2004年11月16日(火).
情報処理Ⅱ 2005年10月28日(金).
オブジェクト指向言語論 第二回 知能情報学部 新田直也.
アルゴリズムとデータ構造 2010年6月17日
情報処理Ⅱ 2006年11月8日(金).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 2005年12月16日(火).
情報処理Ⅱ 第2回 2004年10月12日(火).
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2003年11月19日(第6回) 木村巌.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
C言語講座第5回 2017 構造体.
情報処理Ⅱ 2006年10月27日(金).
情報処理Ⅱ 第8回:2003年12月9日(火).
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
Presentation transcript:

情報処理Ⅱ 2006年12月15日(金)

前回の補足1 ライブラリ関数の分類 関数・定数・独自型などをまとめて,他のプログラムから利用できるよう部品化したものを「ライブラリ」という. 標準ライブラリ関数(標準関数,ANSI準拠の関数) この科目で使用するのは,この範囲だけ POSIX準拠の関数 情報ネットワーク演習で使用する その他(サードパーティライブラリ) OpenGL(ビジュアル情報演習で使用する) 関数・定数・独自型などをまとめて,他のプログラムから利用できるよう部品化したものを「ライブラリ」という. http://ja.wikipedia.org/wiki/POSIX ANSI: American National Standard Institute POSIX: Portable Operating System Interface for UNIX

前回の補足2 複雑な式も,木構造(構文木)で表現できる. コンパイラは,ソースコード(文字列)をこの種の木構造で表現し,それから計算機が実行できるコード(オブジェクトコード)に変換する.処理の中で,再帰呼び出しが用いられることがある. 「s != NULL && *s != '\0'」の 構文木 && != != s NULL * '\0' 「構文木」は「こうぶんぎ」という. 構文木と再帰の関係について興味がある人は,「再帰的下向き構文解析法」を自習してほしい. s

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

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

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]; と同じ 構造体の型名定義によく用いられる.

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

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

列挙型の使用例 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[6][mloop] = ...; } 13 型と変数を同時に定義 年月単位の降水量を格納する

汎整数型 整数型(char,int,long など)と列挙型を合わせて, 汎整数型(integral type)という. ただし,利用は代入,比較,範囲内の増分・減分にとどめておく.

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

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

構造体の定義の例(2) 構造体宣言と変数定義を一つの文で 構造体宣言と型定義を一つの文で struct point { double x; double y; } p; 構造体宣言と型定義を一つの文で typedef struct point { double x, y; } point; point p; 構造体宣言と型定義とを同時に行った場合, struct point型とpoint型とで相互に参照・代入してよい. struct point型と point型が定義される

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

構造体の定義の例(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を介することなく, 直接各要素の値を獲得したり,書き換えたりすることはできない. 下の構造体について,行列の各要素は,構造体オブジェクトの外で確保することになる.

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

構造体の参照と代入(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

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

両替問題の仕様(1) 両替機の両替部分をシミュレート(模擬)する. 入金に対して,どの紙幣・貨幣を何枚出せばいいかを出力する. 「崩す」(一万円札を千円札10枚にするなど)のは考えない. 金額に関する情報 一万円,五千円,千円の各紙幣(bill)の枚数 500円,100円,50円,10円,5円,1円の各硬貨(coin)の枚数 合計金額(amount) ⇒ 構造体のメンバ? 100 100 100 100 500 50 10 10 10 5 5 5 5

両替問題の考え方 知りたい情報,行いたい操作 紙幣・貨幣がそれぞれ何枚ある(入金された,出金しないといけない)かを知る 合計金額を求める 両替する 両替前の「紙幣・貨幣の枚数の情報」に対して, 両替後の「紙幣・貨幣の枚数の情報」を求める

両替問題のプログラミング(1) 金銭構造体 struct money {  int bill_10000, bill_5000, bill_1000;  int coin_500, coin_100, coin_50, coin_10, coin_5, coin_1;  };

両替問題のプログラミング(2) 定義した関数 void print_money(struct money *moneyp); 枚数と総額を出力する 構造体のポインタを引数にとる int calc_amount(struct money *moneyp); 総額を求める struct money change_money(struct money money_in); 両替する 構造体オブジェクトを引数にとり,構造体オブジェクトを返す 「calc」は,「calculate (計算する)」という単語による.

その他の話題 構造体と配列の使い分け sizeof(構造体) 構造体とプログラミング してはいけないこと 独自の型はどこで定義する?

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

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

構造体とプログラミング さまざまな種類の情報を持つ「実体」を一つのオブジェクトとして処理したいとき, まず,「何に処理をしたいか?」を考える. そのオブジェクトの型を構造体で定義する. 座標上の点,学生情報,ノード(節点),など. 次に,「何の処理をしたいか?」を考える. 構造体を引数にとって処理する関数を定義する. 引数・戻り値ともに,型は構造体そのものにすべきか, 構造体のポインタにすべきか,そのつど検討する.

してはいけないこと × 関数内のauto変数を指し示すポインタを,戻り値とする. struct money *create_money(void) {   struct pocket money = {     0, 0, 0, 0, 0, 0, 0, 0, 0 }; return &money; } コンパイルエラーにはならないが,実行時に支障をきたす. 関数処理が終わると,moneyの領域が破棄される ⇒ *(&money)が不定!

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

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

予告 次回授業終了後すぐ,授業Webページにて,第2回レポート課題を掲示します.