プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

20
ププププププププププ8プ ププププププ ププ プププププ ププ [email protected]

Upload: isi

Post on 05-Jan-2016

48 views

Category:

Documents


0 download

DESCRIPTION

プログラミング演習 Ⅱ 第 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 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

プログラミング演習Ⅱ第 8 回

マクロ・列挙体等

情報・知能工学系山本一公

[email protected]

Page 2: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

前回の課題の解説・ポイント(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

Page 3: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

前回の課題の解説・ポイント(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));}

Page 4: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

課題5の採点結果から• 課題 5−2

– 今の関数呼び出しが初めてかどうか( W を直接返すかどうか)を判定するために、変数を用意すること自体は正しい

– その変数の初期値として 0 を代入しておき、その変数が 0 なら初めての呼び出しなので、 1 を代入すれば良いだけ

– 呼ばれる度にその変数に 1 を加算する必要はない• 初めてかどうかだけが判定できれば良いのだから• 加算し続けると、そのうち 0 に戻ってしまって、予期せぬ

不具合が起きる可能性がある

Page 5: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

課題6の採点結果から• 課題 6−2

– ビット数を数える必要がある• やり方は正しければ何でも良い

– 大域変数 count を用意して、 count_bits() でカウントさせている人がいる• この場合、 rrotate()/lrotate() より先に、 count_bits()

が一度呼び出されている必要がある– それをプログラマがやらないといけない

• 関数が独立していない。使うとき注意が必要になる

– 実装としてあまり好ましくない

Page 6: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

今日の内容• 教科書 pp.183 ~ 193, 198 ~ 205

– 再帰は来年になってから

• 関数形式マクロ– コンマ演算子

• 列挙体– 列挙定数

• 入出力と文字– getchar(), putchar(), EOF– JIS コード (ASCII コード )

Page 7: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

関数形式マクロ(1)• 関数っぽくマクロを書くことができます

– 引数・返却値の型を気にしなくてもよい• ただし、自動的に型が拡張されるので注意!

– マクロなので、コンパイル時に展開される• 通常、プログラムサイズ⇒大、速度⇒高

#define sqr(x) ((x) * (x)) /* 二乗を計算する関数形式マクロ */

printf(“ その数の二乗は %d です。 \n”, sqr(nx));

Page 8: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

関数形式マクロ(2)• 副作用に注意

– sqr(a++) (a++)*(a++)⇒– 意図しない結果に!

• 引数・マクロ全体を () でくくろう!– 式を入れるとおかしなことに

#define add(x,y) x + y

z = add(a, b) * add(c, d); ⇒ z = a + b * c + d; 意図しない結果に!

Page 9: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

関数形式マクロ(3)• “{“ と” }” で囲んでブロックを作って、その中に

処理(複数の文)を書く• 「手続き形式マクロ」とも呼ぶ

• 教科書では間違いの例として紹介されているが、

if 文のブロックを” {” と” }” で囲まなかったのが問題

• この書き方自体が悪い訳ではない

#define putsa(str) { putchar(’_a’); puts(str); }

Page 10: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

コンマ演算子• “,” で式をつなぐと、一つの式になる

– 左から順に評価される– これを利用して、先の例を常に問題が出ない

ように書き直すことができる

– 警報を発して文字列を表示するマクロ

#define putsa(str) ( putchar(‘\a’), puts(str) )

Page 11: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

関数形式マクロの展開のされ方を見る

• コンパイルするときに、 gcc にオプションとして” -E” を与える– “gcc –E list8-1.c” のようにする– コンパイルされず、前処理 (preprocess) だけが行わ

れる• C 言語ソースファイル中の” #” で始まる行の処理( #define

や #include )だけが行われる

• 関数型でもマクロなので「コンパイル前に文字の置き換えが行われるだけ」なことに注意せよ

Page 12: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

列挙体(1)• 値の集合を表すデータ構造

– メンバーに順番に値が割り当てられる

– 列挙定数は int 型

enum animal { Dog, Cat, Monkey, Invalid };/* Dog = 0, Cat = 1, Monkey = 2, Invalid = 3 となる */

enum animal select(void) /* 返り値が enum 型 */{ int tmp; … return (tmp); /* 実際の返り値は int 型 */}

Page 13: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

列挙体(2)• 列挙体メンバーは定数

– case 文で使える

–上手く使えれば便利

enum animal selected;

do { switch (selected = select()) { case Dog : dog(); break; case Cat : cat(); break; case Monkey : monkey(); break; } while (selected != Invalid);

Page 14: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

列挙定数• 列挙定数は値を変えられる

• 途中でも変えられる

• 月名と月数の対応

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 };

Page 15: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

入出力関数と EOF• getchar()

–標準入力(キーボード)から1文字読み込む– 返却値は int 型。読み込んだ文字を返す– ファイルの終端かエラーで EOF を返す

• EOF: ファイルの終端( End of File )の意。stdio.h 内で定義されている。

• putchar()–標準出力(端末画面)へ1文字書き込む– 返却値は int 型。書き込んだ文字を返す–エラーで EOF を返す

Page 16: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

文字(1)• 文字には「文字コード」という数値が割り当てられている– 文字はコンピュータ内部では数値として扱われている

• JIS コード表( p.200, Table 8-1 )–アルファベット・半角カナと文字コードの対応表• アルファベットの部分は ASCII コードと同じ

Page 17: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

文字(2)• 1文字をシングルクォートで囲むと

文字コード(数値)になる

• 拡張表記– p.203, Table 8-2– printf() や puts() の中でも使う

‘0’= 0x30, ‘1’= 0x31, ‘A’= 0x41, ‘a’= 0x61, ……

Page 18: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

今週の課題1. 教科書 p.187, 演習 8-3 のプログラムを作成せ

よ。 main 関数等も作成して、完成したプログラムを作成すること。gcc に” -E” オプションを与えて、関数形式マクロが正しく展開されていることを確かめること。

2. 教科書 p.205, 演習 8-8 のプログラムを作成せよ。※ヒント:基本的には、1文字ずつ読み込んで、改行があったら数えている行数を増やせばよい。行の途中で EOF は出ないと考えて良い※キーボードから EOF を出すには” Ctrl + D”

Page 19: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

レポートについて• 電子メールで提出

– 提出先は [email protected]– Subject を「プログラミング演習2 課題 7提出 学籍

番号・氏名 」とすること– C 言語ソースファイルを添付する

• メールの本文には何も書かなくて良いです– ソースファイルの頭にコメントで以下の情報を入れる

• 学籍番号・氏名• プログラムの説明(どのように動くのか、工夫した点等)• 実行結果(長い場合は一部)を貼る

– 提出締切は、 12月 12 日(水) 12:00 (1週間後)

Page 20: プログラミング演習 Ⅱ 第 8 回 マクロ・列挙体等

授業用 Web サイト• URL:

http://www.slp.cs.tut.ac.jp/~kyama/programming2/– 課題の pdf ファイルが置いてあります。– 授業で使った ppt ファイルを置いていきます。

• 質問メールは、以下のどちらかのアドレスまで– [email protected][email protected]

• C-515へ直接質問しに来ても構いません