200 likes | 363 Views
プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等. 情報・知能工学系 山本一公 kyama@tut.jp. 前回の課題の解説・ポイント(1). 課題6-1 プログラム そのもの は 特にどうということは ない 出力は全部 unsigned にキャスト char / signed char / unsigned char : 1 byte signed short int / unsigned short int : 2 byte signed int / unsigned int : 4 byte
E N D
プログラミング演習Ⅱ第8回マクロ・列挙体等プログラミング演習Ⅱ第8回マクロ・列挙体等 情報・知能工学系 山本一公 kyama@tut.jp
前回の課題の解説・ポイント(1) • 課題6-1 • プログラムそのものは特にどうということはない • 出力は全部 unsigned にキャスト • char / signed char / unsigned char : 1 byte • signed short int / unsigned short int : 2 byte • signed int / unsigned int : 4 byte • signed long int / unsigned long int : 8 byte • signed long longint / unsigned long longint : 8 byte • float : 4 byte • double : 8 byte • long double : 16 byte
前回の課題の解説・ポイント(2) • 課題6-2 • 説明スライドの通り • 右シフトと左シフトを組み合わせることで回転を実現する unsigned lrotate(unsigned x, int n) /* 左回転 */ { return (x << n | x >> (sizeof(unsigned)* 8 – n)); } unsigned rrotate(unsigned x, int n) /* 右回転 */ { return (x >> n | x << (sizeof(unsigned) * 8 – n)); }
課題5の採点結果から • 課題5−2 • 今の関数呼び出しが初めてかどうか(Wを直接返すかどうか)を判定するために、変数を用意すること自体は正しい • その変数の初期値として0を代入しておき、その変数が0なら初めての呼び出しなので、1を代入すれば良いだけ • 呼ばれる度にその変数に1を加算する必要はない • 初めてかどうかだけが判定できれば良いのだから • 加算し続けると、そのうち0に戻ってしまって、予期せぬ不具合が起きる可能性がある
課題6の採点結果から • 課題6−2 • ビット数を数える必要がある • やり方は正しければ何でも良い • 大域変数countを用意して、count_bits()でカウントさせている人がいる • この場合、rrotate()/lrotate()より先に、count_bits()が一度呼び出されている必要がある • それをプログラマがやらないといけない • 関数が独立していない。使うとき注意が必要になる • 実装としてあまり好ましくない
今日の内容 • 教科書 pp.183~193, 198~205 • 再帰は来年になってから • 関数形式マクロ • コンマ演算子 • 列挙体 • 列挙定数 • 入出力と文字 • getchar(), putchar(), EOF • JISコード (ASCIIコード)
関数形式マクロ(1) • 関数っぽくマクロを書くことができます • 引数・返却値の型を気にしなくてもよい • ただし、自動的に型が拡張されるので注意! • マクロなので、コンパイル時に展開される • 通常、プログラムサイズ⇒大、速度⇒高 #define sqr(x) ((x) * (x)) /* 二乗を計算する関数形式マクロ */ … printf(“その数の二乗は%dです。\n”, sqr(nx));
関数形式マクロ(2) • 副作用に注意 • sqr(a++) ⇒ (a++)*(a++) • 意図しない結果に! • 引数・マクロ全体を ()でくくろう! • 式を入れるとおかしなことに #define add(x,y) x + y … z = add(a, b) * add(c, d); ⇒ z = a + b * c + d; 意図しない結果に!
関数形式マクロ(3) • “{“と”}”で囲んでブロックを作って、その中に処理(複数の文)を書く • 「手続き形式マクロ」とも呼ぶ • 教科書では間違いの例として紹介されているが、if文のブロックを”{”と”}”で囲まなかったのが問題 • この書き方自体が悪い訳ではない #define putsa(str) {putchar(’_a’); puts(str);}
コンマ演算子 • “,”で式をつなぐと、一つの式になる • 左から順に評価される • これを利用して、先の例を常に問題が出ないように書き直すことができる • 警報を発して文字列を表示するマクロ #define putsa(str) (putchar(‘\a’), puts(str) )
関数形式マクロの展開のされ方を見る • コンパイルするときに、gccにオプションとして”-E”を与える • “gcc –E list8-1.c” のようにする • コンパイルされず、前処理(preprocess) だけが行われる • C言語ソースファイル中の”#”で始まる行の処理(#defineや#include)だけが行われる • 関数型でもマクロなので「コンパイル前に文字の置き換えが行われるだけ」なことに注意せよ
列挙体(1) • 値の集合を表すデータ構造 • メンバーに順番に値が割り当てられる • 列挙定数はint型 enum animal { Dog, Cat, Monkey, Invalid }; /* Dog = 0, Cat = 1, Monkey = 2, Invalid = 3となる */ enum animal select(void) /* 返り値がenum型 */ { inttmp; … return (tmp); /* 実際の返り値はint型 */ }
列挙体(2) • 列挙体メンバーは定数 • case文で使える • 上手く使えれば便利 enum animal selected; do { switch (selected = select()) { case Dog : dog(); break; case Cat : cat(); break; case Monkey : monkey(); break; } while (selected != Invalid);
列挙定数 • 列挙定数は値を変えられる • 途中でも変えられる • 月名と月数の対応 enum animal { Dog = 1, Cat, Monkey, Invalid }; /* Dog = 1, Cat = 2, Monkey = 3, Invalid = 4となる */ enum animal { Dog, Cat= 3, Monkey, Invalid }; /* Dog = 0, Cat = 3, Monkey = 4, Invalid = 5となる */ enum month { January = 1, February, March, April, …, December };
入出力関数とEOF • getchar() • 標準入力(キーボード)から1文字読み込む • 返却値は int型。読み込んだ文字を返す • ファイルの終端かエラーでEOFを返す • EOF: ファイルの終端( End of File)の意。stdio.h内で定義されている。 • putchar() • 標準出力(端末画面)へ1文字書き込む • 返却値は int 型。書き込んだ文字を返す • エラーでEOFを返す
文字(1) • 文字には「文字コード」という数値が割り当てられている • 文字はコンピュータ内部では数値として扱われている • JISコード表(p.200, Table 8-1) • アルファベット・半角カナと文字コードの対応表 • アルファベットの部分はASCIIコードと同じ
文字(2) • 1文字をシングルクォートで囲むと文字コード(数値)になる • 拡張表記 • p.203, Table 8-2 • printf()やputs()の中でも使う ‘0’= 0x30, ‘1’= 0x31, ‘A’= 0x41, ‘a’= 0x61, ……
今週の課題 • 教科書p.187, 演習8-3のプログラムを作成せよ。main関数等も作成して、完成したプログラムを作成すること。gccに”-E”オプションを与えて、関数形式マクロが正しく展開されていることを確かめること。 • 教科書p.205, 演習8-8のプログラムを作成せよ。※ヒント:基本的には、1文字ずつ読み込んで、改行があったら数えている行数を増やせばよい。行の途中でEOFは出ないと考えて良い※キーボードからEOFを出すには”Ctrl + D”
レポートについて • 電子メールで提出 • 提出先は prog2@slp.cs.tut.ac.jp • Subjectを「プログラミング演習2 課題7提出 学籍番号・氏名 」とすること • C言語ソースファイルを添付する • メールの本文には何も書かなくて良いです • ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る • 提出締切は、12月12日(水) 12:00 (1週間後)
授業用Webサイト • URL: http://www.slp.cs.tut.ac.jp/~kyama/programming2/ • 課題のpdfファイルが置いてあります。 • 授業で使ったpptファイルを置いていきます。 • 質問メールは、以下のどちらかのアドレスまで • kyama@tut.jp • prog2@slp.cs.tut.ac.jp • C-515へ直接質問しに来ても構いません