スライド8

プログラミング演習Ⅱ
第8回
マクロ・列挙体等
情報・知能工学系
山本一公
[email protected]
前回の課題の解説・ポイント(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 long int / unsigned long long int : 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)
• “{“と”}”で囲んでブロックを作って、その中に
処理(複数の文)を書く
• 「手続き形式マクロ」とも呼ぶ
#define putsa(str) { putchar(’_a’); puts(str); }
• 教科書では間違いの例として紹介されているが
、
if文のブロックを”{”と”}”で囲まなかったのが問
題
• この書き方自体が悪い訳ではない
コンマ演算子
• “,”で式をつなぐと、一つの式になる
– 左から順に評価される
– これを利用して、先の例を常に問題が出ない
ように書き直すことができる
– 警報を発して文字列を表示するマクロ
#define
putsa(str)
( putchar(‘\a’), puts(str) )
関数形式マクロの
展開のされ方を見る
• コンパイルするときに、gccにオプションとし
て”-E”を与える
– “gcc –E list8-1.c” のようにする
– コンパイルされず、前処理 (preprocess) だけが行われ
る
• C言語ソースファイル中の”#”で始まる行の処理(#defineや
#include)だけが行われる
• 関数型でもマクロなので「コンパイル前に文字
の置き換えが行われるだけ」なことに注意せよ
列挙体(1)
• 値の集合を表すデータ構造
– メンバーに順番に値が割り当てられる
enum animal { Dog, Cat, Monkey, Invalid };
/* Dog = 0, Cat = 1, Monkey = 2, Invalid = 3となる */
enum animal select(void) /* 返り値がenum型 */
{
int tmp;
…
return (tmp); /* 実際の返り値はint型 */
}
– 列挙定数は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文字をシングルクォートで囲むと
文字コード(数値)になる
‘0’= 0x30, ‘1’= 0x31, ‘A’= 0x41, ‘a’= 0x61, ……
• 拡張表記
– p.203, Table 8-2
– printf()やputs()の中でも使う
今週の課題
1. 教科書p.187, 演習8-3のプログラムを作成せよ。
main関数等も作成して、完成したプログラムを
作成すること。
gccに”-E”オプションを与えて、関数形式マク
ロが正しく展開されていることを確かめること。
2. 教科書p.205, 演習8-8のプログラムを作成せよ。
※ヒント:基本的には、1文字ずつ読み込んで、
改行があったら数えている行数を増やせばよい。
行の途中でEOFは出ないと考えて良い
※キーボードからEOFを出すには”Ctrl + D”
レポートについて
• 電子メールで提出
– 提出先は [email protected]
– Subjectを「プログラミング演習2 課題7提出
号・氏名 」とすること
– C言語ソースファイルを添付する
学籍番
• メールの本文には何も書かなくて良いです
– ソースファイルの頭にコメントで以下の情報を入れる
• 学籍番号・氏名
• プログラムの説明(どのように動くのか、工夫した点等)
• 実行結果(長い場合は一部)を貼る
– 提出締切は、12月12日(水) 12:00 (1週間後)
授業用Webサイト
• URL:
http://www.slp.cs.tut.ac.jp/~kyama/programming2/
– 課題のpdfファイルが置いてあります。
– 授業で使ったpptファイルを置いていきます。
• 質問メールは、以下のどちらかのアドレスまで
– [email protected][email protected]
• C-515へ直接質問しに来ても構いません