情報処理Ⅱ 2007年12月3日(月) その2.

Slides:



Advertisements
Similar presentations
情報処理Ⅱ 第12回 2005 年 01 月 18 日(火). 2 本日学ぶこと 前処理指令 関数プロトタイプ ライブラリ関数の活用 関数は  すでにあるものを使うか?  関数として定義するか?  関数形式マクロとして定義するか?
Advertisements

情報処理Ⅱ 第7回:2003年12月2日(火). 問題(授業がつまらない人のため に) ぷよ連結問題 前提 : フィールドを2次元 配列で定義し,各マスの 「ぷよ」を int 型の値で表現 する. ある地点を入力に取り,そ れと連結する「ぷよ」の個 数を求めよ. 消去できる「ぷよ」 (N 個以上 連結するぷよと,それに隣接する特.
2.5 プログラムの構成要素 (1)文字セット ① ASCII ( American Standard Code for Interchange ) JIS コードと同じ ② EBCDIC ( Extended Binary Coded Decimal for Information Code ) 1.
情報処理Ⅱ 2006年12月8日(金).
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
コンパイラ 2011年10月17日
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第2回ネットワークプログラミング 中村 修.
情報処理Ⅱ 2007年12月17日(月).
情報処理Ⅱ 2005年12月9日(金).
情報処理Ⅱ 2005年12月22日(木).
第8回 プログラミングⅡ 第8回
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
コンパイラ 2012年10月15日
情報処理Ⅱ 2006年1月13日(金).
情報処理Ⅱ 第9回 2004年12月7日(火).
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
プログラミング演習I 2003年6月25日(第10回) 木村巌.
プログラミング演習I 2003年5月7日(第4回) 木村巌.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
前回の練習問題.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
第5回放送授業.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
情報処理Ⅱ 第14回 2006年1月23日(月).
情報処理Ⅱ 第2回:2003年10月14日(火).
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
コンパイラ 2011年10月20日
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 2006年11月24日(金).
情報処理Ⅱ 第7回 2004年11月16日(火).
コンパイラ 2012年10月11日
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
関数と再帰 教科書13章 電子1(木曜クラス) 2005/06/22(Thu.).
情報処理Ⅱ 2007年2月2日(金).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 第2回 2004年10月12日(火).
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
第10回 関数と再帰.
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
情報処理Ⅱ 第9回:2003年12月16日(火).
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
計算技術研究会 第5回 C言語勉強会 関数(function)を使う
岩村雅一 知能情報工学演習I 第13回(後半第7回) 岩村雅一
情報処理Ⅱ 第8回:2003年12月9日(火).
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

情報処理Ⅱ 2007年12月3日(月) その2

本日学ぶこと 再帰(recursion) ⇒自己言及なくして情報技術を語るなかれ ライブラリ関数 ⇒先人の知恵を拝借 ライブラリ関数 ⇒先人の知恵を拝借 共通するキーワード:関数の活用

前回の補足:関数の抽出 関数を抽出することで一般に 関数抽出の要点 コード量(プログラムのサイズ,ステップ数)は増える. しかし,それぞれの関数のコード量は減り,関数ごとに役割が明確になるため,読みやすい. 関数抽出の要点 ①関数名,②戻り値の型,③仮引数 の順に決める. 変数の有効範囲に注意する. 仮引数と実引数が同じ名前でも,別オブジェクト. 変数の除去や複製が必要なこともある. 保守性向上

再帰呼び出しとは 関数の内部で自分自身を呼び出すことを,再帰呼び出し(リカーシブコール,recursive call)という. 用途 注意点 再帰的(帰納的,循環的)な定義 バックトラック(backtrack) 分割統治法(divide-and-conquer) 注意点 無限ループにならないようにする. 再帰を使わないほうがよいこともある. 「データ構造とプログラ ミング技法」他で リp.121, pp.363-364

階乗を求める関数 階乗 プログラムコード 0! = 1, 1! = 1 n! = n×(n-1)! (n≧2) int factorial(int x) { if (x <= 1) return 1; else return x * factorial(x - 1); } 関数factorialの中で 関数factorialを 呼び出している…再帰! factorial.c

なぜ再帰呼び出しが可能なのか? 同一の変数名x に対して複数の このようなデータ 構造を,「スタック」 オブジェクトが という. 生成される. このようなデータ 構造を,「スタック」 という. factorial x = 1 factorial x = 2 factorialの再帰呼び出しを終えたときの戻り先 factorialの呼び出し(関数処理)を終えたときの戻り先 factorial関数処理時に 生成されるオブジェクト main x = 3 Cの規格として「スタック」が必須ということではない. しかし,関数呼び出しの構造(mainから関数Aを呼び出し,関数Aの中で関数Bを呼び出し,関数Bの処理を終えたら, 制御は,mainではなく,「関数Aの中で関数Bを呼び出したところ」に戻らなければならない(そして,関数Aの処理を 終えたら,制御は,mainの中で関数Aを呼び出したところに戻る))を実行時に保持するには,スタックが最も合理的 ということである. main関数処理時に 生成されるオブジェクト num = 3 入p.285

カウントダウン,カウントアップ countdown(5); ⇒ 5 4 3 2 1 0 countup(5); ⇒ 0 1 2 3 4 5 カウントアップ,カウントダウンともに,再帰呼び出しなしの プログラムのほうが,効率はよい. なぜ再帰呼び出しは効率が悪いか? …関数呼び出しのコスト(オーバーヘッド)があるから. 業務としてのプログラミングで,再帰呼び出しを使用してはならないと(コーディング規約で)定めていることも 再帰呼び出しはしてはいけないと書いている例: 『組み込みソフトウェア開発向けコーディング作法ガイド』p.49 『ずっと受けたかったソフトウェアエンジニアリングの授業2』pp.121-122 countdown.c, countup.c

再帰的な定義の例(1) 階乗 フィボナッチ数列 最大公約数 再帰呼び出しを用いれば,シンプルに書ける. 0! = 1, 1! = 1 n! = n×(n-1)! (n≧2) フィボナッチ数列 a1 = 1, a2 = 1 an = an-1 + an-2  (n≧3) 最大公約数 gcd(n,0) = 0 gcd(n,m) = gcd(m,n%m) (m>0) 再帰呼び出しを用いれば,シンプルに書ける. しかしこれらも,whileループのほうが効率がよい. 最大公約数の式について,n=0や,n<mのときにも成り立つ. (例:gcd(0, 5) = gcd(5, 0) = 0; gcd(9,12) = gcd(12,9) = gcd(9,3) = gcd(3,0) = 3)

再帰的な定義の例(2) 木構造 再帰呼び出しは必要? トーナメント表の決勝戦から順に見て, 優勝チームの戦績を知る 100万個の記録から,欲しいものを 瞬時に獲得する ホームディレクトリ以下のすべての ファイル名を出力する 再帰呼び出しは必要? するのが自然な場合と,してはいけない 場合がある 呼び出し方よりもデータ構造のほうが重要 「100万個~瞬時に獲得する」と木構造の結びつきは自明でないが,2年後期の「データベース」で学んでほしい. 「ホームディレクトリ以下のすべてのファイル名を出力する」には,いちいちプログラムを作らなくても, 「find ~」を実行するだけでいい.

再帰的な定義の例(3) 文法 計算機でどう処理する? BNF記法 <識別子> ::= <識別子> <英字> | <識別子> <数字> | <識別子> '_' | <英字> | '_' 句構造文法による式の定義 計算機でどう処理する? 字句解析・構文解析を行う. 再帰下降構文解析は,文法と対応した 解析器(パーサ)を生成するが,効率は 必ずしも良くない. a=b++-+c; ↓ 字句解析 構文解析 OK a=b++++c; NG 再帰下降構文解析 http://ja.wikipedia.org/wiki/%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90 構文解析などに関する基本書籍:中田育男: コンパイラ, 産業図書, 1981. 「b(符号) (符号) (符号) (符号)c」の式で文法的に正しいものはどれか検証している文献:Lepton: Lepton先生のCの強化書, 翔泳社, pp.217-225, 2007. リpp.170-172

次に学ぶこと ライブラリ関数の活用 (参考)関数の分類 先人の知恵を活用する. 勉強・授業のためでなければ, ライブラリ関数と同じ名前や機能の関数は自作しない. (参考)関数の分類 自作関数: 自分で定義する.⇒ 11月26日のテーマ ライブラリ関数: 出来合いのもの.printfなど.⇒ ここでのテーマ 入p.111

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

ライブラリ関数とヘッダファイル 既に定義されている関数や定数を利用するには,あらかじめ,適切なファイル名(ヘッダファイル)を記載しておく. printf なら #include <stdio.h> CHAR_BIT なら #include <limits.h> ライブラリ関数と,記載すべきヘッダファイル名は,オンラインマニュアルで知ることができる. man 3 printf jman 3 printf JM Project (http://www.linux.or.jp/JM/) ヘッダファイルはコンパイル環境が保有しているが,その所在は,環境による. Vine Linuxでおすすめ リp.369の最後に「詳細は,27.10節を参照して下さい.」とあるが,27.10節は存在しない. 入p.114 リp.369, pp.395-396, p.473, p.421

ヘッダファイルとインクルード ヘッダファイルには,定数,構造体や特殊な型,関数プロトタイプなどが宣言されている. #include <stdlib.h> とすると,/usr/include/stdlib.h を取り込む(インクルードする). 慣例として,ファイル名は「.h」で終わらせる. ヘッダファイルの中で,他のヘッダファイルをインクルードすることもよく行われる. ヘッダファイルを自作することもある.そのファイルをインクルードするときは,#include "headerfile.h" のように書く. 「.c」や「.h」などを,Windowsユーザは「拡張子」と呼んでいるが, Unix文化では「サフィックス(suffix)」と呼ばれている. リp.395-396

有用なライブラリ関数(1) #include <stdio.h> を必要とするもの int printf(const char *format, ...); int scanf(const char *format, ...); int putchar(int c); … 1文字出力 int getchar(void); … 1文字入力 int sprintf(char *str, const char *format, ...); … printfと同様に文字列を構成し,結果をstr(の指し示す配列領域)に格納する 可変引数 と呼ばれる 可変引数 と呼ばれる リp.455, p.139

有用なライブラリ関数(2) #include <stdlib.h> を必要とするもの int atoi(char *s); … 文字列から整数値への変換 void exit(int status); … プログラムの終了 int rand(void); … 乱数生成 #include <string.h> を必要とするもの size_t strlen(char *s); … 文字列の長さ int strcmp(char *s1, char *s2); … 文字列比較 char *strstr(char *s1, char *s2); … 文字列検索 char *strcat(char *dest, char *src); … 文字列連結 #include <string.h>を必要とするものについて, strcatのdestを除き,char *型の仮引数には,constがつく. リp.493, p.511

有用なライブラリ関数(3) #include <ctype.h> を必要とするもの int isdigit(int c); … 文字が数字であるか判定 isalphaは英字判定,isalnumは英数字判定 int tolower(int c); … 大文字を小文字に変換 大文字以外の文字はそのまま 逆はtoupper #include <math.h> を必要とするもの double exp(double x); … eのx乗 double floor(double x); … x以下で最小の整数 最大はceil,四捨五入(丸め)はround コンパイル時,「cc -lm program.c」のようにリンカオプション(linker option)が必要 リp.411, p.432

関数名の表記 printf関数,関数printf printf()関数,関数printf() printf(3) この授業で採用している. 関数名であることを明確にする表記法.よく見かける. printf(3) 「printfというライブラリ関数があって,詳細は, man 3 printfを実行すれば得られる」の意味. 「(1)」ならコマンド,「(2)」はシステムコール man printfを実行すると,ライブラリ関数ではなく,コマンドとしてのprintfの使い方が出てくる. 「printfの実引数に3と書く」ではない.

まとめ 再帰呼び出しを用いて関数を定義すると,プログラムがすっきり書けることがある. 一般に,再帰を用いないほうが効率的である. 再帰的に定義された問題に適用すると,効果的. 一般に,再帰を用いないほうが効率的である. 関数内のauto変数は,関数呼び出しごとに生成される. ライブラリ関数の活用により,先人の知恵を活用しながら,信頼性の高いソフトウェアが作れる. 関数名,処理内容,ヘッダファイル,引数,戻り値を把握する. 教科書だけでなく,オンラインマニュアルやインターネットの情報も参考に.