情報処理Ⅱ 2005年12月22日(木).

Slides:



Advertisements
Similar presentations
情報処理Ⅱ 第8回 2004 年 11 月 30 日(火). 2 本日学ぶこと 関数と変数 目的  関数を自分で定義し,変数の利用方法・範囲を明示的に制 限することで,適切な機能分割(モジュール化,再利用) を図る. してはいけないこと  main 関数のみで 100 行以上のプログラム  グローバル変数を駆使するプログラム.
Advertisements

情報処理Ⅱ 第7回:2003年12月2日(火). 問題(授業がつまらない人のため に) ぷよ連結問題 前提 : フィールドを2次元 配列で定義し,各マスの 「ぷよ」を int 型の値で表現 する. ある地点を入力に取り,そ れと連結する「ぷよ」の個 数を求めよ. 消去できる「ぷよ」 (N 個以上 連結するぷよと,それに隣接する特.
【事例演習5】  字句解析     解 説  “ハッシュを用いた字句解析の方法”.
情報処理Ⅱ 第11回 2004年12月21日(火).
情報処理演習 (9)グラフィックス システム科学領域 日浦 慎作.
情報処理Ⅱ 第10回 2004年12月14日(火).
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
ファーストイヤー・セミナーⅡ 第8回 データの入力.
第12回構造体.
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
情報処理Ⅱ 2007年12月17日(月).
情報処理Ⅱ 2005年12月9日(金).
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
情報処理Ⅱ 第9回 2004年12月7日(火).
関数 関数とスタック.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング言語入門 手続き型言語としてのJava
プログラミング2 関数
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
Cプログラミング演習 第7回 メモリ内でのデータの配置.
アルゴリズムとデータ構造1 2006年6月16日
プログラミング 4 記憶の割り付け.
前回の練習問題.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
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.
アルゴリズムとデータ構造 2010年7月26日
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
コンパイラ 2011年10月20日
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
復習 2次元配列 4列 j = 0 j = 1 j = 2 j = 3 i = 0 i = 1 i = 2 3行
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
高度プログラミング演習 (09).
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
アルゴリズムとデータ構造1 2008年7月24日
情報処理Ⅱ 第2回 2005年10月14日(金).
情報処理Ⅱ 第2回 2006年10月13日(金).
地域情報学 C言語プログラミング 第4回 while文、do~while文、switch文、 2次元配列、ポインタ 2017年11月10日
第5回 プログラミングⅡ 第5回
高度プログラミング演習 (11).
情報処理Ⅱ 2006年12月22日(金).
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 2006年11月24日(金).
情報処理Ⅱ 第7回 2004年11月16日(火).
情報処理Ⅱ 2007年12月3日(月) その1.
プログラミング 4 文字列.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
Q q 情報セキュリティ 第8回:2004年5月28日(金) の補足 q q.
関数と再帰 教科書13章 電子1(木曜クラス) 2005/06/22(Thu.).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 第2回 2004年10月12日(火).
情報処理Ⅱ 2005年11月25日(金).
第10回 関数と再帰.
プログラミング基礎a 第5回 C言語によるプログラミング入門 配列と文字列
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
情報処理Ⅱ 第3回 2004年10月19日(火).
情報処理Ⅱ 2006年10月20日(金).
情報処理Ⅱ 第8回:2003年12月9日(火).
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
プログラミング 2 静的変数.
Presentation transcript:

情報処理Ⅱ 2005年12月22日(木)

本日学ぶこと:プログラミングの例題2つ 暗号化問題 ぷよ連結問題 Wagahai Ha Nekodearu 学ぶこと:配列と写像,static変数 ぷよ連結問題 学ぶこと:列挙型,再帰とトラックバック,多次元配列を引数とする関数 Wagahai Ha Nekodearu Zdjdkdl Kd Qhnrghdux

暗号化問題 仕様 入力文にあるすべての'A'をα,すべての'B'をβ,…に置き換えて出力する.(単一換字暗号という.) 文字は,char型の任意の値とする.ただし'\0'を除く('\0'は必ず'\0'に置き換える,と考えてもよい). どの文字をどの文字に置き換えるかは,プログラムの中で指定する. 簡単な操作で,復号できるようにする.  Wagahai Ha Nekodearu  Zdjdkdl Kd Qhnrghdux 暗号化 復号

暗号化問題 (まずい)方針 'A'をα,'B'をβ,…に置き換えるのを switch~caseで行う. プログラムが無駄に長くなる. 柔軟性に欠ける. char encrypt_char(char c) { switch (c) { case 'A': return 'D'; case 'B': return 'E'; ... }

暗号化問題 encrypt_ table … 'D' 'E' 'F' 'G' … +0 +'A' +'C' +1 +'B' +'D' ... 'E' 'B' 'D' 'A' 変換後 変換前 方針 暗号化のための変換表(暗号化表)を, 配列で保持する. char encrypt_table[256]; encrypt_table['A']の値 encrypt_ table … 'D' 'E' 'F' 'G' … +0 +'A' +'C' +1 +'B' +'D' +255

暗号化問題 方針(続き) 暗号化は,写像を用いる. a = 'A'; のとき,b = encrypt_table[a]; でbの値が'D'となるようにするには,あらかじめencrypt_table['A']の値を'D'としておけばよい. 復号のための変換表(復号表)は,逆写像を用いて求める. char decrypt_table[256]; decrypt_table[encrypt_table['A']] = 'A'; gがfの逆写像 であるとは, g(f(x))=x

暗号化問題 方針(続き) 定義する関数 変換表を恒等写像にする. 暗号化表を設定する. 暗号化表を用いて,復号表を設定する. fが恒等写像 であるとは, f(x)=x 方針(続き) 定義する関数 変換表を恒等写像にする. 暗号化表を設定する. 暗号化表を用いて,復号表を設定する. 変換表を用いて,文字列を暗号化もしくは復号する. 暗号化と復号はどう区別する? 暗号化:./encrypt Wakagai Ha Nekodearu 復号: ./encrypt -d Zdjdkdl Kd Qhnrghdux 「コマンドラインオプション」と呼ばれる

定義する関数(1) void reset_table(char *table); encrypt_ table ? 1 'A' 'B' … 変換表を恒等写像にする. encrypt_ table ? 1 'A' 'B' … 'C' 255 ? … ? ? ? … ? table +0 +'A' +'C' +1 +'B' +255 関数内の ローカル変数 (関数が終了すると,破棄される)

定義する関数(2) void set_encrypt_table(char *table, const char *from, const char *to); 二つの文字列を用いて,暗号化表を設定する. encrypt_ table … 'D' +'A' 'E' +'B' 'F' +'C' … table from to 'A' 'B' 'C' … '\0' 'D' 'E' 'F' … '\0'

定義する関数(3) void set_decrypt_table(char *table, const char *encrypt_table); 暗号化表を用いて,復号表を設定する. decrypt_ table … 'A' … table +0 +'A' +'C' +1 +'B' +'D' +255 encrypt_ table … 'D' … encrypt_ table +0 +'A' +'C' +1 +'B' +'D' +255

定義する関数(4) char *encrypt(const char *text, const char *table); 変換表を用いて,文字列を暗号化もしくは復号する. 「暗号化」と「復号」の処理を共通化している! 戻り値は,変換された文字列で,static変数result(のポインタ値)となる. text 'W' 'a' 'g' 'a' 'h' 'a' 'i' '\0' table … 'D' 'E' 'F' 'G' … result 'Z' 'd' 'j' 'd' 'k' 'd' 'l' '\0' static領域(関数が終了しても,破棄されない) 戻り値

暗号化プログラムの補足 関数set_encrypt_tableの仮引数from, toは const char *型である.このとき fromの参照先(const char型の値)を変更しようとしている. 暗号化のように,関数開始時点で長さがわからない文字列を入力にとり,それと同じ長さの暗号文を返すときは,生成する暗号文が配列領域をはみ出さないように配慮する. encrypt.cでは,100文字を越える入力は,そこから無視している.

ぷよ連結問題 「ぷよ」が配置された2次元空間(フィールド)と,その中の座標を入力に取り,そこと連結する「ぷよ」の個数を求めよ.

フィールドの表現(1) フィールドは2次元 ⇒2次元配列を使用 色は赤・青・黄と空白 ⇒char型で表現 2次元の添字は 先に y 座標 後に x 座標 char field[高さ][幅] = { 0, 0, 3, 0, 0, 0, 3, 3, 2, 1, 0, 1, 1, 3, 2, 2, 2, 2, 1, 1, 2, 3, 3, 2, 1, 2, 2, 3, 1, 3, 2, 2, 1, 3, 3, 3, }; …1 …2 …3 空白…0

フィールドの表現(2) しかし… マスに入る値を列挙型で表現する. マスに入る値はいろいろあるのでは? 色の番号(数値)は重要か? enum puyo { P_EMPTY, P_RED, P_BLUE, P_YELLOW, P_GREEN, P_PURPLE, P_OJAMA, P_MAX }; enum puyo型の値(もしくは整数値)が色ぷよか否かは,自作関数is_coloredで判定する. 7

ぷよ連結問題・再帰版(1) 考え方 着目する地点の上下左右に探索を 広げる. 連結するぷよの個数は, 1 + 「上に伸ばして連結する個数」 + 「下に伸ばして連結する個数」 + 「左に伸ばして連結する個数」 + 「右に伸ばして連結する個数」 探索済の情報を格納しておく. フィールドの値の最上位ビットで 無限ループ回避のため 1 探索済? ぷよの種類

ぷよ連結問題・再帰版(2) 2次元フィールドfieldと,その中の座標(x,y)を入力に取り,そこと色ぷよcolorで連結するぷよの個数calc_puyo(field, x, y, color)は, 座標がフィールド外なら,0 色ぷよでないか,色がcolorと異なっていれば,0 探索済なら,0 以上のいずれでもないなら,そこを探索済とした上で, 1 + calc_puyo(field, x, y-1, color) + calc_puyo(field, x, y+1, color) + calc_puyo(field, x-1, y, color) + calc_puyo(field, x+1, y, color) 自作関数 is_connected 再帰呼び出し!

バックトラック 後戻り法ともいう. 木など,枝分かれする対象をすべて探索するのに有用. 再帰呼び出しを使用し,戻る地点の情報をスタックに乗せる. 」が 戻る地点の情報 「

ぷよ連結問題とバックトラック

再帰は効率的? 6×6のフィールドで全部同じ色ぷよのとき,calc_puyoは 合計36回呼び出される. や などの総数     や   などの総数 最大36段の深さ(level)の呼び出しになる. 図で表示される    や   などの最大の個数

関数の仮引数が配列の形に見えても,それはポインタである. 多次元配列を引数とする関数 (1次元)配列を引数とする関数 char a[] = "wakayama"; len = strlen(a); int strlen(char *s); 多次元配列を引数とする関数 char field[6][6]; color = get_puyo(field, 0, 0); int get_puyo(char field[][6], int x, int y); aは char [9]型の 配列変数 実引数のaは char *型の ポインタ値 仮引数のsは char *型の ポインタ変数 実引数の fieldは char (*)[6]型 のポインタ値 仮引数のfieldは char [ ][6]型 (char (*)[6]型)の ポインタ変数 fieldは char [6][6]型の 配列変数 関数の仮引数が配列の形に見えても,それはポインタである.

仮引数と実引数が同じ名前でいいの? 言語規格上,問題ない. 実用上も便利. 仮引数と実引数の有効範囲が違うから 実用上も便利. 大きな長さの関数を分割したいとき,変数名を共通化すればいいから デメリット:変数名を一括して置換したときに,置換すべきでないものを置換してしまうかも