2018年度「プログラミング言語」配布資料 (12)

Size: px
Start display at page:

Download "2018年度「プログラミング言語」配布資料 (12)"

Transcription

1 2018 年度 プログラミング言語 配布資料 (12) 五十嵐淳 2019 年 1 月 1 日 目次 1 2 分探索木 in C (C/bst/) 分木の表現 探索 挿入 削除 葉を null ポインタで表現する (C/bstNull/) 短命な 2 分探索木 in C (C/bstMutable/) [ 前の資料 講義ホームページ トップ 次の資料 ] 1 2 分探索木 in C (C/bst/) いつものように永続的な 2 分探索木から実装する 分木の表現 2 分木の構造の型定義は,Java や C に比べると複雑である. まず, 大枠としては, 節点の種類 ( 葉は枝か ) を表すデータと 節点の情報を表すデータを構造体で組にする. struct tree { T1 tag; // for representing the kind of a node T2 dat; // for representing the node itself } タグ名を tree, メンバを tag, dat とした. これにより struct tree 型の変数 t に対して,t.tag が節点の種類を,t.dat が節点 ( 葉か枝 ) のデータを表す表現となる. 種類を表す部分の名前を tag にしているのは, 1

2 データに, それが何を表すかのデータ ( いわばメタデータ ) を付加する時に タグ付け ということから付けたが, 構造体や共用体の名前を表す C 言語用語の タグ と紛らわしかったもしれない. 節点の種類を表すデータは ( 整数でもよいのだが ) 列挙型を用いよう. また節点は, 葉と枝を表すデータの共用体で定義する. struct tree { enum nkind { LEAF, BRANCH } tag; union lf_or_br { T3 lf; // for representing a leaf T4 br; // for representing a branch } dat; } enum や union に nkind (node の kind) と lf_or_br (lf または br) という名前をつけたが, これらの型 (enum nkind 型や union lf_or_br 型 ) を持つ変数を使うつもりがないので, これらは実は省略可能である ( 実際, サンプルコードでは lf_or_br は省いた ). ここまでの部分は OCaml で書くと, type tree = Lf of T3 Br of T4 というような定義に対応する.OCaml の場合は Lf は何も情報を運ばないので,of T3 以下は削除,T4 として, レコード型 {left: tree; value: int; right: tree} を使った. ここでは,lf の型 T3 部分は ( どうせ使わないので ) 何でもよいのだが, 統一感から (?) 構造体を入れておくことにする. メンバも与える必要はないが, メンバを持たない構造体は許されていないので ( 試した限りでコンパイラは受理してくれるようだが ), ダミーのメンバを持つ構造体 struct leaf { int dummy; } lf; とした. 枝の方は,3 メンバを持つ構造体になるのだが,OCaml に倣って, struct branch { struct tree left; int value; struct tree right; } br; とすると, コンパイルエラーになってしまう.(MacOSX の clang コマンドでコンパイルした場合は以下のようなメッセージが表示される.) bst.c:16:19: error: field has incomplete type 'struct tree' struct tree left; ^ エラーメッセージがわかりにくいが,incomplete type というのは ( その型の値が占める領域の ) サイズがわからない型のことである. コンパイラは,struct tree の定義を処理するにあたって, その構造体のサイズを計 2

3 算する必要がある. しかし, 定義の中に, 今まさに定義しようとしている型が出てきてしまい, その型のサイズがわからない, といっているのである. エラーメッセージとしては, 型のサイズがわからない, といっているが, 実は, このような定義は許しようがない. struct tree,enum nkind,struct leaf,int のサイズをそれぞれ s, e, l, i とすると,s = e+max(l, (s+i+s)) を満たす必要がある ( 足し算が構造体,max が共用体のサイズ計算に対応している ) が, これらのサイズは全て正整数なので, こんな s は存在しないわけである. 要するに, ある領域の中に, すっぽりと自分自身をふたつもを含むようなレイアウトをしなければいけないのだが, そんなことは不可能なのである. このような問題を回避して,C 言語で再帰的なデータ構造を扱うためには, ポインタを使うことになる. 以下が最終的な struct tree の定義である. メンバ left, right はポインタになっている. struct tree { enum nkind { LEAF, BRANCH } tag; union { struct leaf { int dummy; } lf; struct branch { struct tree *left; int value; struct tree *right; } br; } dat; // standing for DATum }; このように, 枝は部分木へのポインタをメンバとするように定義する. ポインタであれば, その指す先の領域に関わらずポインタのサイズは一定であるため, 先ほどのサイズを計算する式も,p をポインタのサイズとして,s = e + max(l, (p + i + p)) で与えることができる 寄り道 先程も少し触れたように, 葉を表すためのデータは何もないので,struct leaf... lf; を共用体に含める必要は全くない. さらに,2 分木の場合, このメンバを削除すると, 共用体のメンバ数が 1 になってしまい, 共用体を使う意味すらなくなるため, struct tree { enum nkind { LEAF, BRANCH } tag; struct branch { struct tree *left; int value; struct tree *right; } br; }; という定義でプログラムを作ることも可能であるが, ここでは一般性を考慮して, 少し煩雑な定義のまま話を進める. 3

4 1.1.2 補助関数 探索などの関数定義に進む前に,branch や leaf を作るための関数を用意しておく. これらは Java でいえばコ ンストラクタの定義に相当するものと考えられる.branch であれば, 左右の部分木 ( へのポインタ ) と格納す る整数を引数として, それらを格納した枝 ( へのポインタ ) を返す関数として定義する. 1 struct tree *newbranch(struct tree *left, int value, struct tree *right) { 2 // Allocate a new object in the heap 3 struct tree *n = (struct tree *)malloc(sizeof(struct tree)); 4 // And then initialize the members 5 n->tag = BRANCH; // could be written (*n).tag = BRANCH 6 n->dat.br.left = left; 7 n->dat.br.value = value; 8 n->dat.br.right = right; 9 return n; 10 } struct tree *newleaf(void) { 13 struct tree *n = (struct tree *)malloc(sizeof(struct tree)); 14 n->tag = LEAF; 15 return n; 16 } どちらの関数でも n を malloc で確保した領域へのポインタとして使っている.struct tree は内部に共用体さらには構造体を含んでいるので, どの部分にどのような表記でアクセスするかに注目して定義を読んでもらいたい. この際, n->dat は共用体 n->dat.br は共用体を構造体 struct branch として使うためのメンバアクセス さらにそれに.left などをつけることでようやく, 部分木 ( へのポインタ ) などにアクセスできる. 1.2 探索 さて, ここまできちんと理解できれば 2 分探索木を操作する関数の定義はさほど難しくはない. 以下は find の定義である. 1 bool find(struct tree *t, int n) { 2 if (t->tag == LEAF) { 3 return false; 4 } else /* t->tag == BRANCH */ { 5 struct branch b = t->dat.br; 6 if (n == b.value) { 7 return true; 8 } else if (n < b.value) { 4

5 9 return find(b.left, n); 10 } else /* n > b.value */ { 11 return find(b.right, n); 12 } 13 } 14 } 2 行目で節点の種類によって場合分けを行い,5 行目で branch の構造体を取り出し, その値とパラメータ n の大小によって場合分けを行う 寄り道 (C 上級者への道 ) 5 行目で, struct branch b = t->dat.br; としているが, これだと, 変数 b の領域に構造体全体の内容がコピーされるので, 効率を気にする場合はポインタ操作で済ませるのが C らしいプログラミングである. struct branch *b = &(t->dat.br); // could be &t->dat.br &(t->dat.br) ( この括弧も不要だがわかりやすさのためにつけている ) によって,t の領域の途中 ( 構造体 branch が始まる部分 ) を指すポインタが得られる. もちろんこの場合,b の型が構造体ではなく構造体へのポインタになるので, 以降の木の操作には. ではなく -> を使うよう変更が必要である. struct branch *b = &(t->dat.br); if (n == b->value) { return true; } else if (n < b->value) { return find(b->left, n); } else /* n > b->value */ { return find(b->right, n); } 1.3 挿入 挿入については, あまりコメントすることがない. 1 struct tree *insert(struct tree *t, int n) { 2 if (t->tag == LEAF) { 3 return newbranch(newleaf(), n, newleaf()); 4 } else /* t->tag == BRANCH */ { 5 struct branch b = t->dat.br; 5

6 6 if (n == b.value) { 7 return t; 8 } else if (n < b.value) { 9 return newbranch(insert(b.left, n), b.value, b.right); 10 } else /* n > b.value */ { 11 return newbranch(b.right, b.value, insert(b.right, n)); 12 } 13 } 14 } 1.4 削除 削除についてもあまりコメントすることがない.min 関数中で, ライブラリの assert マクロ 1 が呼ばれているが, これは min 関数は branch のみに適用されるべきものなので, 引数が本当に branch かどうかを確認している.( 万が一 branch でなかったら, その時点で実行が終了する.) 1 int min(struct tree *t) { 2 assert(t->tag == BRANCH); 3 struct branch b = t->dat.br; 4 if (b.left->tag == LEAF) { 5 return b.value; 6 } else { 7 return min(b.left); 8 } 9 } struct tree *delete(struct tree *t, int n) { 12 if (t->tag == LEAF) { 13 return t; 14 } else /* t->tag == BRANCH */ { 15 struct branch b = t->dat.br; 16 if (n == b.value) { 17 if (b.left->tag == LEAF) { 18 if (b.right->tag == LEAF) { 19 return newleaf(); 20 } else /* b.right->tag == BRANCH*/ { 21 return b.right; 22 } 23 } else /* b.left->tag == BRANCH*/ { 24 if (b.right->tag == LEAF) { 1 assert は関数に見えるが, 実は関数ではなく,C 言語のマクロ (macro) と呼ばれる機能を使って定義されている. マクロはいわば略記であって, コンパイラ ( 正確にはプリプロセッサ ) によって定義が展開されて, プログラムの字面上の置き換えが起こる. マクロについては, いずれ講義でも触れたい. 6

7 25 return b.left; 26 } else /* b.right->tag == BRANCH*/ { 27 int m = min(b.right); 28 struct tree *newright = delete(b.right, m); 29 return newbranch(b.left, m, newright); 30 } 31 } 32 } else if (n < b.value) { 33 struct tree *newleft = delete(b.left, n); 34 return newbranch(newleft, b.value, b.right); 35 } else /* n > b.value */ { 36 struct tree *newright = delete(b.right, n); 37 return newbranch(b.left, b.value, newright); 38 } 39 } 40 } 1.5 葉を null ポインタで表現する (C/bstNull/) Java の時と同様に,2 分木の表現のバリエーションとして, 何の情報も運ばない leaf を null pointer で表現する方法を紹介する.null pointer は, 何の領域も指さない特殊なポインタである.malloc で確保した領域も含め, いかなる変数のアドレスとも異なる. 既に紹介した通り C 言語では null pointer は NULL という定数で表す. leaf を NULL で表すことにすると, そもそも共用体を使う必要がなくなる 2 ので, 型の定義は非常に単純になる. 1 struct tree { 2 struct tree *left; 3 int value; 4 struct tree *right; 5 }; leaf, branch を作る補助関数 1 struct tree *newbranch(struct tree *left, 2 int value, 3 struct tree *right) { 4 // Allocate a new object in the heap 5 struct tree *n = (struct tree *)malloc(sizeof(struct tree)); 6 // And then initialize the members 2 繰り返すが, これはこのデータ構造の特殊事情である. もしも,leaf, branch 以外にデータを構成する種類があったら共用体を使うこ とになる. 7

8 7 n->left = left; 8 n->value = value; 9 n->right = right; 10 return n; 11 } struct tree *newleaf(void) { 14 /* Real C programmers would avoid defining such a simple function. 15 * It causes overhead of function calls. 16 */ 17 return NULL; 18 } コメントにもあるように,newleaf は常に NULL を返す関数である. 効率重視のふつうの C プログラマであれば, こんな関数は定義しない (newleaf() を使うところを NULL で置き換える ) と思うが, 最初の実装方法との対応を取りやすくするために, あえて定義している. 残りの関数の定義を一気に示す. 与えられた木が leaf か branch か判定するために,null pointer との比較 (t == NULL) を行っていること,struct tree の定義が簡単になった分,b を用意する必要がなくなったことなどに注意すれば, 理解できるはずである.( ほとんど Java バージョンと同じであるし, むしろ, こちらの方がプログラムとしてはスッキリしているといってもよいだろう.) 1 bool find(struct tree *t, int n) { 2 if (t == NULL) { 3 return false; 4 } else /* t is a branch */ { 5 if (n == t->value) { 6 return true; 7 } else if (n < t->value) { 8 return find(t->left, n); 9 } else /* n > t->value */ { 10 return find(t->right, n); 11 } 12 } 13 } struct tree *insert(struct tree *t, int n) { 16 if (t == NULL) { 17 return newbranch(newleaf(), n, newleaf()); 18 } else /* t is a branch */ { 19 if (n == t->value) { 20 return t; 21 } else if (n < t->value) { 22 return newbranch(insert(t->left, n), t->value, t->right); 8

9 23 } else /* n > t->value */ { 24 return newbranch(t->right, t->value, insert(t->right, n)); 25 } 26 } 27 } int min(struct tree *t) { 30 assert(t!= NULL); 31 /* t is a branch */ 32 if (t->left == NULL) { 33 return t->value; 34 } else { 35 return min(t->left); 36 } 37 } struct tree *delete(struct tree *t, int n) { 40 if (t == NULL) { 41 return t; 42 } else /* t is a branch */ { 43 if (n == t->value) { 44 if (t->left == NULL) { 45 if (t->right == NULL) { 46 return newleaf(); 47 } else /* t->right is a branch */ { 48 return t->right; 49 } 50 } else /* t->left is a branch */ { 51 if (t->right == NULL) { 52 return t->left; 53 } else /* t->right is a branch */ { 54 int m = min(t->right); 55 struct tree *newright = delete(t->right, m); 56 return newbranch(t->left, m, newright); 57 } 58 } 59 } else if (n < t->value) { 60 struct tree *newleft = delete(t->left, n); 61 return newbranch(newleft, t->value, t->right); 62 } else /* n > t->value */ { 63 struct tree *newright = delete(t->right, n); 64 return newbranch(t->left, t->value, newright); 65 } 9

10 66 } 67 } 1.6 短命な 2 分探索木 in C (C/bstMutable/) 次は, 短命な実装である. 木構造のデータ定義は (NULL を使わない ) 最初と同じであるので,newbranch,newleaf なども含めて省略する. また find は木を書き換えないので, これも定義は同じであるので省略する. insert で注意すべき点は, leaf を branch に変化させる時には,leaf の領域が不要になるので free で解放している (3 行目 ) branch を表す構造体は局所変数にコピーせずに & でポインタを取得している (6 行目, 上記 寄り道 (C 上級者への道 ) も参照). コピーしてしまうと, 元の木構造を書き換えることにならないので, これは必須である. といったあたりであろう. 1 struct tree *insert(struct tree *t, int n) { 2 if (t->tag == LEAF) { 3 free(t); 4 return newbranch(newleaf(), n, newleaf()); 5 } else /* t->tag == BRANCH */ { 6 struct branch *b = &(t->dat.br); 7 if (n == b->value) { 8 return t; 9 } else if (n < b->value) { 10 struct tree *newleft = insert(b->left, n); 11 b->left = newleft; 12 return t; 13 } else /* n > b->value */ { 14 struct tree *newright = insert(b->right, n); 15 b->right = newright; 16 return t; 17 } 18 } 19 } 削除についても, 不要な領域の解放が注意点だろう (19-21 行目,25-26 行目,32-33 行目 ). しかも, 解放の順番も大事である. 先に free(t) としてしまうと,b の指す領域 ( これは t の領域の途中を指しているのであった ) も解放されてしまうので,free(b->left); や free(b->right); が未定義動作を引き起こす不正な操作になってしまう. 解放する時には子供から が大原則である. 1 int min(struct tree *t) { 2 assert(t->tag == BRANCH); 3 struct branch *b = &(t->dat.br); 10

11 4 if (b->left->tag == LEAF) { 5 return b->value; 6 } else { 7 return min(b->left); 8 } 9 } struct tree *delete(struct tree *t, int n) { 12 if (t->tag == LEAF) { 13 return t; 14 } else /* t->tag == BRANCH */ { 15 struct branch *b = &(t->dat.br); 16 if (n == b->value) { 17 if (b->left->tag == LEAF) { 18 if (b->right->tag == LEAF) { 19 free(b->left); 20 free(b->right); 21 free(t); 22 return newleaf(); 23 } else /* b->right->tag == BRANCH*/ { 24 struct tree *right = b->right; 25 free(b->left); 26 free(t); 27 return right; 28 } 29 } else /* b->left->tag == BRANCH*/ { 30 if (b->right->tag == LEAF) { 31 struct tree *left = b->left; 32 free(b->right); 33 free(t); 34 return left; 35 } else /* b->right->tag == BRANCH*/ { 36 int m = min(b->right); 37 struct tree *newright = delete(b->right, m); 38 b->value = m; 39 b->right = newright; 40 return t; 41 } 42 } 43 } else if (n < b->value) { 44 struct tree *newleft = delete(b->left, n); 45 b->left = newleft; 46 return t; 11

12 47 } else /* n > b->value */ { 48 struct tree *newright = delete(b->right, n); 49 b->left = newright; 50 return t; 51 } 52 } 53 } メモリの解放を本当に気にするなら,main 関数を終了する前に, 確保した領域を全て解放するのが行儀のよいプログラムである. 以下は, 与えられた木の領域を全て解放する関数 free_tree である.main ( ここには掲載していない ) の最後で読んでいる. void free_tree(struct tree *t) { if (t->tag == LEAF) { free(t); } else /* t->tag == BRANCH */ { struct branch *b = &(t->dat.br); free_tree(b->left); free_tree(b->right); free(t); } return; } 葉を null ポインタで表現する (C/bstMutableNull/) 最後に, 短命でかつ葉を NULL で表現したバージョンである. おそらく, これが C 言語で 2 分探索木を実装する場合の標準的な実装のひとつだろう.( おそらく一部の関数は再帰を使わずに繰り返しを使って定義すると, より C らしい. これについては 06-rec-iter.html を参照のこと.) ほとんどの定義は, これまでの内容が理解できていればそれほど難しくはないが, 挿入と削除関連のメモリ管理についてコメントする. 1 struct tree *insert(struct tree *t, int n) { 2 if (t == NULL) { 3 return newbranch(newleaf(), n, newleaf()); 4 } else /* t is a branch */ { 5 if (n == t->value) { 6 return t; 7 } else if (n < t->value) { 8 t->left = insert(t->left, n); 9 return t; 10 } else /* n > t->value */ { 11 t->right = insert(t->right, n); 12

13 12 return t; 13 } 14 } 15 } // The definition of 18 // int min(struct tree *); 19 // omitted struct tree *delete(struct tree *t, int n) { 22 if (t == NULL) { 23 return t; 24 } else /* t is a branch */ { 25 if (n == t->value) { 26 if (t->left == NULL) { 27 if (t->right == NULL) { 28 free(t); 29 return newleaf(); 30 } else /* t->right is a branch */ { 31 struct tree *right = t->right; 32 free(t); 33 return right; 34 } 35 } else /* t->left is a branch */ { 36 if (t->right == NULL) { 37 struct tree *left = t->left; 38 free(t); 39 return left; 40 } else /* t->right is a branch */ { 41 int m = min(t->right); 42 t->value = m; 43 t->right = delete(t->right, m); 44 return t; 45 } 46 } 47 } else if (n < t->value) { 48 t->left = delete(t->left, n); 49 return t; 50 } else /* n > t->value */ { 51 t->right = delete(t->right, n); 52 return t; 53 } 54 } 13

14 55 } まず,leaf については何の領域も確保されていないので,free をする必要はない (3 行目 ). また, 削除操作で, 部分木を残したまま, それをぶら下げている branch を解放する場合には, まず, 部分木へのポインタを保存しておいてから, 領域の解放, 保存しておいたポインタを返している (31-33 行目,37-39 行目 ). これを free(t); return t->right; などとすると, 解放した領域にアクセスすることになってしまう ( 未定義動作 ) のでまずい. [ 前の資料 講義ホームページ トップ 次の資料 ] 14

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション プログラミング応用演習 第 4 回再帰的構造体 プログラミングを 余談 : 教えることの難しさ 丁寧に説明しないと分かってもらえない 説明すると 小難しくなる学生が目指すべきところプログラム例を説明されて理解できる違うやり方でも良いので自力で解決できる おっけー 動けば良い という意識でプログラミング 正しく動くことのチェックは必要 解答例と自分のやり方との比較が勉強になる 今日のお題 再帰的構造体

More information

第2回

第2回 明星大学情報学科 年後期 アルゴリズムとデータ構造 Ⅰ 第 回 Page 第 回基本データ構造 連結リストとその操作 -. リスト構造 データ部 と ポインタ部 で構成され ポインタをたどることによりデータを扱うことができる構造 -. 単方向リストとその操作 --. 単方向リスト 次のデータへのポインタを つだけ持っているデータ構造 ( データ部は 複数のデータを持っている場合もある ) データ部

More information

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ 今回のプログラミングの課題 次のステップによって 徐々に難易度の高いプログラムを作成する ( 参照用の番号は よくわかる C 言語 のページ番号 ) 1. キーボード入力された整数 10 個の中から最大のものを答える 2. 整数を要素とする配列 (p.57-59) に初期値を与えておき

More information

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科 バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科 ポインタ変数の扱い方 1 ポインタ変数の宣言 int *p; double *q; 2 ポインタ変数へのアドレスの代入 int *p; と宣言した時,p がポインタ変数 int x; と普通に宣言した変数に対して, p = &x; は x のアドレスのポインタ変数 p への代入 ポインタ変数の扱い方 3 間接参照 (

More information

プログラミングI第10回

プログラミングI第10回 プログラミング 1 第 10 回 構造体 (3) 応用 リスト操作 この資料にあるサンプルプログラムは /home/course/prog1/public_html/2007/hw/lec/sources/ 下に置いてありますから 各自自分のディレクトリにコピーして コンパイル 実行してみてください Prog1 2007 Lec 101 Programming1 Group 19992007 データ構造

More information

Taro-2分探索木Ⅰ(公開版).jtd

Taro-2分探索木Ⅰ(公開版).jtd 2 分探索木 Ⅰ 0. 目次 1. 2 分探索木とは 2. 2 分探索木の作成 3. 2 分探索木の走査 3. 1 前走査 3. 2 中走査 3. 3 問題 問題 1 問題 2 後走査 4. 2 分探索木の表示 - 1 - 1. 2 分探索木とは 木はいくつかの節点と節点同士を結ぶ辺から構成される 2 つの節点 u,v が直接辺で結ばれているとき 一方を親節点 他方を子節点という ある節点の親節点は高々

More information

PowerPoint Template

PowerPoint Template プログラミング演習 Ⅲ Linked List P. Ravindra S. De Silva e-mail: [email protected], Room F-413 URL: www.icd.cs.tut.ac.jp/~ravi/prog3/index_j.html 連結リストとは? 一つひとつの要素がその前後の要素との参照関係をもつデータ構造 A B C D 連結リストを使用する利点 - 通常の配列はサイズが固定されている

More information

memo

memo 数理情報工学演習第一 C プログラミング演習 ( 第 5 回 ) 2015/05/11 DEPARTMENT OF MATHEMATICAL INFORMATICS 1 今日の内容 : プロトタイプ宣言 ヘッダーファイル, プログラムの分割 課題 : 疎行列 2 プロトタイプ宣言 3 C 言語では, 関数や変数は使用する前 ( ソースの上のほう ) に定義されている必要がある. double sub(int

More information

Microsoft PowerPoint - algo ppt [互換モード]

Microsoft PowerPoint - algo ppt [互換モード] ( 復習 ) アルゴリズムとは アルゴリズム概論 - 探索 () - アルゴリズム 問題を解くための曖昧さのない手順 与えられた問題を解くための機械的操作からなる有限の手続き 機械的操作 : 単純な演算, 代入, 比較など 安本慶一 yasumoto[at]is.naist.jp プログラムとの違い プログラムはアルゴリズムをプログラミング言語で表現したもの アルゴリズムは自然言語でも, プログラミング言語でも表現できる

More information

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用 RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用体型のローカル変数を文字列操作関数で操作する場合の注意事項 (RXC#013) 配列型構造体または共用体の配列型メンバから読み出した値を動的初期化に用いる場合の注意事項

More information

02: 変数と標準入出力

02: 変数と標準入出力 C プログラミング入門 基幹 7 ( 水 5) 13: 構造体 Linux にログインし 以下の講義ページを開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/cpr1/ 2016-07-06 1 例題 : 多角形の面積 n = 5 (5 角形 ) の例 n 1 n 1 1 p 1 T 0 S = i=0 p 0 T i = i=0 2

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション 講座準備 講座資料は次の URL から DL 可能 https://goo.gl/jnrfth 1 ポインタ講座 2017/01/06,09 fumi 2 はじめに ポインタはC 言語において理解が難しいとされる そのポインタを理解することを目的とする 講座は1 日で行うので 詳しいことは調べること 3 はじめに みなさん復習はしましたか? 4 & 演算子 & 演算子を使うと 変数のアドレスが得られる

More information

Taro-ポインタ変数Ⅰ(公開版).j

Taro-ポインタ変数Ⅰ(公開版).j 0. 目次 1. ポインタ変数と変数 2. ポインタ変数と配列 3. ポインタ変数と構造体 4. ポインタ変数と線形リスト 5. 問題 問題 1 問題 2-1 - 1. ポインタ変数と変数 ポインタ変数には 記憶領域の番地が格納されている 通常の変数にはデータが格納されている 宣言 int *a; float *b; char *c; 意味ポインタ変数 aは 整数型データが保存されている番地を格納している

More information

Microsoft Word - 第5回 基本データ構造2(連結リスト).doc

Microsoft Word - 第5回 基本データ構造2(連結リスト).doc 第 5 回基本データ構造 2 連結リストとその操作 第 5 回 Page 1 5-1. リスト構造 データ部 と ポインタ部 で構成され ポインタをたどることによりデータを扱うことができる構造 5-2. 単方向リストとその操作 5-2-1. 単方向リスト 次のデータへのポインタを 1 つだけ持っているデータ構造 ( データ部は 複数のデータを持っている場合もある ) データ部 ポインタ部 ノード リストを構成する要素のことを

More information

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft PowerPoint - CproNt02.ppt [互換モード] 第 2 章 C プログラムの書き方 CPro:02-01 概要 C プログラムの構成要素は関数 ( プログラム = 関数の集まり ) 関数は, ヘッダと本体からなる 使用する関数は, プログラムの先頭 ( 厳密には, 使用場所より前 ) で型宣言 ( プロトタイプ宣言 ) する 関数は仮引数を用いることができる ( なくてもよい ) 関数には戻り値がある ( なくてもよい void 型 ) コメント

More information

Taro-スタック(公開版).jtd

Taro-スタック(公開版).jtd 0. 目次 1. 1. 1 配列によるの実現 1. 2 再帰的なデータ構造によるの実現 1. 3 地図情報処理 1. 4 問題 問題 1 グラフ探索問題 - 1 - 1. は データの出し入れが一カ所で行われ 操作は追加と削除ができるデータ構造をいう 出入口 追加 削除 操作 最初 111 追加 111 222 追加 111 222 333 追加 111 222 333 444 追加 111 222

More information

02: 変数と標準入出力

02: 変数と標準入出力 C プログラミング入門 総機 1 ( 月 1) 11: 動的メモリ確保 Linux にログインし 以下の講義ページを開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/cpr1/ 2015-06-22 1 まとめ : ポインタを使った処理 内容 説明 呼び出し元の変数を書き換える第 9 回 文字列を渡す 配列を渡す 第 10 回 ファイルポインタ

More information

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド メソッド ( 教科書第 7 章 p.221~p.239) ここまでには文字列を表示する System.out.print() やキーボードから整数を入力する stdin.nextint() などを用いてプログラムを作成してきた これらはメソッドと呼ばれるプログラムを構成する部品である メソッドとは Java や C++ などのオブジェクト指向プログラミング言語で利用されている概念であり 他の言語での関数やサブルーチンに相当するが

More information

プログラミング実習I

プログラミング実習I プログラミング実習 I 05 関数 (1) 人間システム工学科井村誠孝 [email protected] 関数とは p.162 数学的には入力に対して出力が決まるもの C 言語では入出力が定まったひとまとまりの処理 入力や出力はあるときもないときもある main() も関数の一種 何かの仕事をこなしてくれる魔法のブラックボックス 例 : printf() 関数中で行われている処理の詳細を使う側は知らないが,

More information

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留

数はファイル内のどの関数からでも参照できるので便利ではありますが 変数の衝突が起こったり ファイル内のどこで値が書き換えられたかわかりづらくなったりなどの欠点があります 複数の関数で変数を共有する時は出来るだけ引数を使うようにし グローバル変数は プログラムの全体の状態を表すものなど最低限のものに留 第 10 章分割コンパイル 1 ソースを分割する今まで出てきたソースは全て一つのソースファイルにソースを記述してきました しかし ソースが長くなっていくと全てを一つのファイルに書くと読みづらくなります そこで ソースを複数のファイルに分割してコンパイルを行う分割コンパイルをします 今章は章名にもなっている 分割コンパイルの方法についてやります 分割コンパイルする時は大抵 関連性のある機能ごとにファイルにまとめます

More information

02: 変数と標準入出力

02: 変数と標準入出力 C プログラミング入門 基幹 2 ( 月 4) 11: 動的メモリ確保 Linux にログインし 以下の講義ページを開いておくこと http://www-it.sci.waseda.ac.jp/ teachers/w483692/cpr1/ 2014-06-22 1 まとめ : ポインタを使った処理 内容 説明 呼び出し元の変数を書き換える第 9 回 文字列を渡す 配列を渡す 第 10 回 ファイルポインタ

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション プログラミング応用演習 第 5 回演習 前回までのお話 ポインタ ポインタを用いた文字列処理 構造体 ファイル 再帰的構造体 リスト構造 動的メモリ管理 今日のお題 ポインタやファイルなど これまでの内容の練習 教材 以前 以下に単語を収録したファイルがあることを紹介した : /usr/share/dict/words この中からランダムに単語を取り出したファイルを用意した http://sun.ac.jp/prof/yamagu/2019app/

More information

株式会社アルウィン C 言語コーディング規約 ver.0.1

株式会社アルウィン C 言語コーディング規約 ver.0.1 C 言語コーディング規約 ver.0.1 1. はじめに本コーディング規約は ( 株 ) アルウィン社内で作成する C 言語ソースコードの可読性 メンテナンス性の向上 丌具合の混入を防ぎやすくするための記述方法及び 推奨する記述方法を記述した文書である 2. 目的 本コーディング規約は ソースコードの可読性 メンテナンス性の向上 丌具合の混入 を可能な限り防ぎ 品質の高いソースコードを作成する一助とすることを目的とする

More information

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版   Copyright 2018 NTT DATA INTRAMART CORPORATION 1 Top 目次 1. 改訂情報 2. はじめに 2.1. 本書の目的 2.2. 対象読者 2.3. サンプルコードについて 2.4. 本書の構成 3. 辞書項目 API 3.1. 最新バージョン 3.1.1. 最新バージョンの辞書を取得する 3.2. 辞書項目 3.2.1. 辞書項目を取得する 3.2.2.

More information

alg2015-6r3.ppt

alg2015-6r3.ppt 1 アルゴリズムとデータ 構造 第 6 回探索のためのデータ構造 (1) 補稿 : 木の巡回 ( なぞり ) 2 木の巡回 ( 第 5 回探索 (1) のスライド ) 木の巡回 * (traverse) とは 木のすべての節点を組織だった方法で訪問すること 深さ優先探索 (depth-first search) による木の巡回 *) 木の なぞり ともいう 2 3 1 3 4 1 4 5 7 10

More information

Microsoft Word - no205.docx

Microsoft Word - no205.docx 3 応用 3.1 連結リスト 前回 先頭に追加する例を扱いました しかし start が指す node を変更することから 関数 の戻り値として作成しました 今回は ポインタ変数 start の値を関数で変更できるように ポイ ンタ変数へのポインタを利用します 先頭を削除するものと 最後を削除する関数を追加します ex25.c /* リストの追加と削除 */ typedef struct node

More information

gengo1-11

gengo1-11 関数の再帰定義 自然数 n の階乗 n! を計算する関数を定義してみる 引数は整数 返却値も整数 n! = 1*2*3*... * (n 1)*n である ただし 0! = 1 とする int factorial(int n) int i, tmp=1; if( n>0 ) for(i=1; i

More information

デバッグの工夫

デバッグの工夫 バグを減らす デバッグの工夫 ~ プログラミング実習で生き残るために ~ 2013/02/12 金森由博 よくあるプログラミングの風景 課題めんどくさい とりあえず適当に書くか エラーチェック めんどくさい あとまわし ちゃんと動くかわかんないけど全部書いちゃお ふー やっと全部書けた コンパイルしよ!? エラーメッセージの意味がわからん!! はぁ やっとコンパイルが通った 実行しよ えっ!? なんでセグメンテーション違反!?

More information

Functional Programming

Functional Programming PROGRAMMING IN HASKELL プログラミング Haskell Chapter 7 - Higher-Order Functions 高階関数 愛知県立大学情報科学部計算機言語論 ( 山本晋一郎 大久保弘崇 2013 年 ) 講義資料オリジナルは http://www.cs.nott.ac.uk/~gmh/book.html を参照のこと 0 Introduction カリー化により

More information

メソッドのまとめ

メソッドのまとめ メソッド (4) 擬似コードテスト技法 http://java.cis.k.hosei.ac.jp/ 授業の前に自己点検以下のことがらを友達に説明できますか? メソッドの宣言とは 起動とは何ですか メソッドの宣言はどのように書きますか メソッドの宣言はどこに置きますか メソッドの起動はどのようにしますか メソッドの仮引数 実引数 戻り値とは何ですか メソッドの起動にあたって実引数はどのようにして仮引数に渡されますか

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション プログラマー勉強会 1 回 basic.h 補足 [ 修飾子 ] const 付けた変数は初期化以外で値を設定することができなくなる 定数宣言に使う unsigned 付けた変数は符号がなくなり 正の値しか設定できない [ 条件コンパイル ] #ifdef M ここ以前に M がマクロとして定義されていれば ここ以下をコンパイルする #ifndef M ここ以前に M というマクロが定義されていなければ

More information

COMET II のプログラミング ここでは機械語レベルプログラミングを学びます 1

COMET II のプログラミング ここでは機械語レベルプログラミングを学びます 1 COMET II のプログラミング ここでは機械語レベルプログラミングを学びます 1 ここでは機械命令レベルプログラミングを学びます 機械命令の形式は学びましたね機械命令を並べたプログラムを作ります 2 その前に プログラミング言語について 4 プログラミング言語について 高級言語 (Java とか C とか ) と機械命令レベルの言語 ( アセンブリ言語 ) があります 5 プログラミング言語について

More information

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ 第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイルの作成方法 コンパイル方法について説明します IDL ファイルの作成にあたっては INTERSTAGE

More information

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y 小幡智裕

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y  小幡智裕 Java Script プログラミング入門 3-6~3-7 茨城大学工学部情報工学科 08T4018Y 小幡智裕 3-6 組み込み関数 組み込み関数とは JavaScript の内部にあらかじめ用意されている関数のこと ユーザ定義の関数と同様に 関数名のみで呼び出すことができる 3-6-1 文字列を式として評価する関数 eval() 関数 引数 : string 式として評価する文字列 戻り値 :

More information

JavaプログラミングⅠ

JavaプログラミングⅠ Java プログラミング Ⅰ 2 回目 ようこそ Java へ 今日の講義で学ぶ内容 画面へのメッセージの表示 文字や文字列 数値を表現するリテラル 制御コードを表すエスケープシーケンス 画面出力の基本形 ソースファイル名 : クラス名.java class クラス名 System.out.println(" ここに出力したい文字列 1 行目 "); System.out.println(" ここに出力したい文字列

More information

プログラム言語及び演習Ⅲ

プログラム言語及び演習Ⅲ 平成 28 年度後期データ構造とアルゴリズム期末テスト 各問題中のアルゴリズムを表すプログラムは, 変数の宣言が省略されているなど, 完全なものではありませんが, 適宜, 常識的な解釈をしてください. 疑問があれば, 挙手をして質問してください. 時間計算量をオーダ記法で表せという問題では, 入力サイズ n を無限大に近づけた場合の漸近的な時間計算量を表せということだと考えてください. 問題 1 入力サイズが

More information

データ構造

データ構造 アルゴリズム及び実習 7 馬青 1 表探索 定義表探索とは 表の形で格納されているデータの中から条件に合ったデータを取り出してくる操作である 但し 表は配列 ( 連結 ) リストなどで実現できるので 以降 表 の代わりに直接 配列 や リスト などの表現を用いる場合が多い 表探索をただ 探索 と呼ぶ場合が多い 用語レコード : 表の中にある個々のデータをレコード (record) と呼ぶ フィールド

More information

# let st1 = {name = "Taro Yamada"; id = };; val st1 : student = {name="taro Yamada"; id=123456} { 1 = 1 ;...; n = n } # let string_of_student {n

# let st1 = {name = Taro Yamada; id = };; val st1 : student = {name=taro Yamada; id=123456} { 1 = 1 ;...; n = n } # let string_of_student {n II 6 / : 2001 11 21 (OCaml ) 1 (field) name id type # type student = {name : string; id : int};; type student = { name : string; id : int; } student {} type = { 1 : 1 ;...; n : n } { 1 = 1 ;...; n = n

More information

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション 部内向けスキルアップ研修 組込み OS 自作入門 2014 年 2 月 10st ステップ担当 : 中村 目次 はじめに OSの役割 メモリ管理 メモリ管理実装 プログラムの実行 まとめ はじめに 前回やったこと OS の原型を作成 今回やること 9th ステップでは CPU 時間 という資源管理 本ステップでは メモリ という資源管理 10.1 OS の役割 10.1.1 コンピュータの 3 大要素

More information

Microsoft PowerPoint - lec10.ppt

Microsoft PowerPoint - lec10.ppt 今日の内容, とポインタの組み合わせ, 例題 1. 住所録例題 2. と関数とは. を扱う関数. 例題 3. のリスト とポインタの組み合わせ 今日の到達目標 自分で を定義する 自分で定義したについて, 配列やポインタを作成する データ型 基本データ型 char 文字 (1 文字 ) int 整数 double 浮動小数など その他のデータ型配列 データの並び ( 文字列も, 文字の並び ) ポインタ

More information