1 / 25

情報処理 Ⅱ

情報処理 Ⅱ. 第9回:2003年12月16日(火). 今回からのルール. 構文は, このフォント 使用例は, このフォント. 本日のテーマ. 前処理( preprocessing) # から始まる構文 代表的なライブラリ関数 ライブラリ関数の名前がわかれば,それを自分で使えるようになる!. 問題(授業がつまらない人の ために). 以下の DEBUGPRINT はどういう意味か? そうであることをどのように確認すればよいか? 配布資料のプログラムは仕様通りに動かない.どこをどのように修正すればよいか?. DEBUGPRINT printf(&quot;!<br>&quot;);.

neveah
Download Presentation

情報処理 Ⅱ

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 情報処理Ⅱ 第9回:2003年12月16日(火)

  2. 今回からのルール • 構文は,このフォント • 使用例は,このフォント

  3. 本日のテーマ • 前処理(preprocessing) • # から始まる構文 • 代表的なライブラリ関数 • ライブラリ関数の名前がわかれば,それを自分で使えるようになる!

  4. 問題(授業がつまらない人のために) • 以下のDEBUGPRINTはどういう意味か? そうであることをどのように確認すればよいか? • 配布資料のプログラムは仕様通りに動かない.どこをどのように修正すればよいか? DEBUGPRINT printf("!\n");

  5. 前処理とコンパイル(1) • 前処理・コンパイル・アセンブル・リンクの各処理は通常,コンパイラ(ccなど)が一手に引き受ける. ソースファイル(前処理前) ソースファイル(前処理後) 前処理 コンパイルアセンブル オブジェクトファイル 実行ファイル リンク

  6. 前処理とコンパイル(2) • 前処理は, • 狭義には,「コンパイルに先立って行われる処理」であり,したがってコンパイルとは別 • 広義には,ccでコンパイルすれば自動的に処理してくれる,という意味でコンパイル作業の一部 • 前処理のコマンド(プリプロセッサ)はcpp • Cの前処理以外にも使用可能

  7. 前処理指令(Preprocessing directive) • マクロ定義(#define) • オブジェクト形式マクロ ⇒「定数」の定義 • 関数形式マクロ ⇒「関数もどき」の定義 • マクロ定義無効(#undef) • ソースファイルの取り込み(#include) • 条件付きコンパイル(#if ... #endif)

  8. オブジェクト形式マクロ(1) • 語の置き換えを行う. • #define 置換対象 置換内容 • #define WORD_SIZE 6と記述すると,それ以降int a[WORD_SIZE];は int a[6];と同じ意味になる. • プログラム修正により変わり得る定数値があるときに,よく用いられる. • 配列の上限値,他と区別する値など. • うまく使うことで,定数値を変えるときのプログラム修正箇所を少なくできる.

  9. オブジェクト形式マクロ(2) • 注意点 • 単純に置き換える. • #define WORD_SIZE 6+1に対してint a[WORD_SIZE * 2];は,int a[6+1 * 2];に置き換えられる(意図した動作ではない). • #define WORD_SIZE (6+1)とすればよい. • 語のみを置き換える. • print_WORD_SIZE( )といった「語の一部」や,printf("WORD_SIZE");といった文字列定数は,置き換えない.

  10. 関数形式マクロ(1) • オブジェクト形式マクロとほぼ同じ書式.置換対象に「(…)」をつける. • #define printfint(x) printf("%d\n",x)に対して,printfint(a);は printf("%d\n", a);に置き換えられる. • 注意すべき使用例 • #define add(x, y) x+yに対して,printf("%d", add(1,-1));やprintf("%d", !add(1,1));は意図通りに動作しない. • #define add(x, y) ((x)+(y))としなければならない. このxは変数ではない!

  11. 関数形式マクロ(2) • 置換内容の中で #を用いると,置換対象を文字列にできる. • #define printfint(x) printf(#x " = %d\n", x)に対してprintfint(a);は printf("a"" = %d\n", a);に置き換えられる(これは printf("a = %d\n", a);と同じ). • ##を用いると,前後の語を連結できる. • #define N1 100#define N2 1000#define N(i) N##iに対して,N(2) は,N2 に,そして 1000に置き換えられる. 順に変換(展開)される.

  12. マクロ利用時の注意点 • C言語のキーワードも置換可能. • #define char signed char は文法上問題ないが,よい書き方ではない.より好ましい例: • #define schar signed char • typedef signed char schar; • 同一内容であれば,同じ名前のマクロを複数定義してもよい.(異なっていればコンパイルエラー.) • 置換内容のない名前も定義できる. • #define DEBUG • 末尾にセミコロンをつけない. • #define WORD_SIZE 6;は(たいていの場合)間違い. schar型を新たに定義する.意味は,signed charと同じ.

  13. 例題1(デバッグ) • うまく動かない. • 関数形式マクロを定義して,途中の値を出力するよう埋め込む.

  14. ソースファイルの取り込み • #include <ファイル名> • ライブラリ関数などが宣言されているヘッダファイルを取り込む(インクルードする). • #include "ファイル名" • 自作のファイルを取り込む.

  15. ヘッダファイル • ライブラリ関数の関数プロトタイプ,構造体や特殊な型,定数などが宣言・定義されているファイル. • #include <stdlib.h>とすると,/usr/include/stdlib.h を取り込む(ヘッダファイルの所在は処理系依存). • 自作するときは,ファイル名を「.h」で終わらせるのが慣例.

  16. ヘッダファイルとライブラリ関数 • 既に定義されている関数や定数を利用するには,あらかじめ,適切なヘッダファイルをインクルードしなければならない. • printf なら #include <stdio.h> • NULL なら #include <stdlib.h>が一般的. • インクルードすべきヘッダファイル名は,manpage で知ることができる. • man 3 printf • jman 3 printf • JM Project (http://www.linux.or.jp/JM/)

  17. 例題1(改良) • ライブラリ関数 isdigit を使用して,文字が数字('0'~'9' のいずれか)か否かを判定する. • 定数や関数形式マクロを定義して,値の意味や処理の内容をわかりやすくする.

  18. 条件付きコンパイル(1) • #if 定数式…#endif定数式(前処理時に評価できる式)が真のときに,「…」を残し,そうでなければ「…」を捨てる.

  19. 条件付きコンパイルの基本 参考: Cのif文 if (条件式1) { … } else if (条件式2) { … } else { … } #if 条件式1 … #elif 条件式2 … #else … #endif 条件付きコンパイル(2) • 「#if 定数式」に代えて,「#ifdef 名前」や「#ifndef 名前」も利用可能. • 「#else」や「#elif 定数式」も記述可能. • 条件付きコンパイルは入れ子にできる.

  20. 前処理指令と空白・コメント • 一つの前処理指令は,1行で書かなければならない.ただし, • 行末に「\」を置くことで,複数行で書ける. • 関数形式マクロの場合,括弧の途中で改行できる. • 前処理指令の中でコメント(/* */ もしくは //)を書くことができる.これは前処理時に空白文字に置き換えられる. ...空白は必須 # define printfint( x ) printf ( #x " = %d\n" , x ) ...空白は任意

  21. 有用なライブラリ関数(1) • #include <stdio.h>を必要とするもの • putchar(c) … 1文字出力 • #include <stdlib.h>を必要とするもの • atoi(str) … 文字列からint型数値への変換 • exit(0) … プログラムの終了 • rand( ) … 乱数生成 • #include <string.h>を必要とするもの • strcmp(str1, str2) … 2つの文字列を比較 • strchr(str, c) … 文字検索

  22. 有用なライブラリ関数(2) • #include <ctype.h>を必要とするもの • isdigit(c) ... 文字が数字であるか判定 • tolower(c) … 大文字を小文字に変換 • #include <math.h>を必要とするもの • exp(x) … eのx乗 • floor(x) ... x以下で最大の整数(反対は ceil)

  23. まとめ • 前処理指令をうまく使えば,人間にとって読みやすいプログラムを書くことができる. • 定数・関数マクロの定義 (#define) • 条件付きコンパイル (#if) • ライブラリ関数を使うには,#includeを用いて適切なヘッダファイルをインクルードする.

  24. 今後の予定 • 2004年1月13日(火):第10回 • ストリーム,特に標準入力と標準出力について • 落ち穂拾い • 2004年1月20日(火):おさらい • 2004年1月27日(火):試験 • 2004年2月3日(火)に補講(プログラミング能率向上のノウハウ;採点対象外)をすれば出席する人はどのくらいいますか?

  25. 発展的な話題:関数名の表記法 • printf • 最も単純な表記法. • ただし,コマンド名と一致するケースがある. • printf() • 関数呼び出しであることを明示する表記法. • printf(3) • 「詳細を知りたければ,man 3 printfを実行して読むこと」を含めた表記法. • manpageはこの形式.Webでもときどき見かける.

More Related