情報処理Ⅱ 第12回 2005 年 01 月 18 日(火). 2 本日学ぶこと 前処理指令 関数プロトタイプ ライブラリ関数の活用 関数は  すでにあるものを使うか?  関数として定義するか?  関数形式マクロとして定義するか?

Slides:



Advertisements
Similar presentations
プログラミング 関数編 情報科学科. プログラミングにあたって C 言語では、 main 内に処理を記述 1000 行になるような大きなプログラムでは、 プログラム全体が何をしているのかを把握 することが困難になる 他人が見ると非常に理解しにくい 作成者であっても時が経てば内容を忘れて、他 人が見た時と同じ状況になる.
Advertisements

情報・知能工学系 山本一公 プログラミング演習Ⅱ 第3回 配列(1) 情報・知能工学系 山本一公
情報処理Ⅱ 2006年12月8日(金).
応用理工学情報処理 第1回(2015年10月 5日) 月曜日担当 前島展也 Manaba
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
第2回ネットワークプログラミング 中村 修.
情報処理Ⅱ 2005年12月22日(木).
第6章 2重ループ&配列 2重ループと配列をやります.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
情報処理Ⅱ 2006年1月13日(金).
第7回 条件による繰り返し.
岩村雅一 知能情報工学演習I 第11回(後半第5回) 岩村雅一
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
情報処理Ⅱ 2008年1月21日(月).
情報処理Ⅱ 2007年12月3日(月) その2.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 条件による繰り返し.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
第7回 プログラミングⅡ 第7回
岩村雅一 知能情報工学演習I 第10回(後半第4回) 岩村雅一
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
情報処理Ⅱ 第14回 2006年1月23日(月).
情報処理Ⅱ 第2回:2003年10月14日(火).
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
B演習(言語処理系演習)第2回 田浦.
情報処理Ⅱ 2007年1月19日(金).
C言語 はじめに 2016年 吉田研究室.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング演習I 2003年4月30日(第3回) 木村巌.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
情報処理Ⅱ 第2回 2005年10月14日(金).
情報処理Ⅱ 第2回 2006年10月13日(金).
情報処理Ⅱ 2005年1月25日(火) レポート課題2の解説.
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
情報処理Ⅱ 2006年11月24日(金).
情報処理Ⅱ 第7回 2004年11月16日(火).
情報処理Ⅱ 2005年10月28日(金).
コンパイラ 2012年10月11日
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
全体の流れ 画像ファイルを開き,画像データをメモリ上にロード メモリ上にロードした画像データに処理を加える
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
情報処理Ⅱ 2007年2月2日(金).
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 第2回 2004年10月12日(火).
第3回簡単なデータの入出力.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
情報処理Ⅱ 2005年11月25日(金).
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
情報処理Ⅱ 第9回:2003年12月16日(火).
情報処理Ⅱ 小テスト 2005年2月1日(火).
プログラミング入門2 第3回 条件分岐(2) 繰り返し文 篠埜 功.
復習 いろいろな変数型(2) char 1バイト → 英数字1文字を入れるのにぴったり アスキーコード → 付録 int
情報処理Ⅱ 第3回 2004年10月19日(火).
情報処理Ⅱ 2006年10月20日(金).
情報処理Ⅱ 第8回:2003年12月9日(火).
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
第1章 文字の表示と計算 printfと演算子をやります.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

情報処理Ⅱ 第12回 2005 年 01 月 18 日(火)

2 本日学ぶこと 前処理指令 関数プロトタイプ ライブラリ関数の活用 関数は  すでにあるものを使うか?  関数として定義するか?  関数形式マクロとして定義するか?

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

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

5 前処理指令 (Preprocessing directive) #define マクロ定義 (#define)  オブジェクト形式マクロ ⇒「定数」の定義  関数形式マクロ ⇒「関数もどき」の定義 #include ソースファイルの取り込み (#include) #if#endif 条件付きコンパイル (#if... #endif など ) 「プリプロセッサ 指令」ともいう

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

7 オブジェクト形式マクロ(2) 注意点 #define WORD_SIZE 6+1  前提: #define WORD_SIZE 6+1  単純に置き換える. int a[WORD_SIZE * 2];int a[6+1 * 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");print_WORD_SIZE( ) といった「語の一部」や, printf("WORD_SIZE"); といった文字列定数は,置 き換えない.

8 オブジェクト形式マクロ(3) 注意点(続き)  予約語も置換可能. #define char signed char typedef signed char schar;#define char signed char は文法上問題ないが, よい書き方ではない.現在では, typedef signed char schar; とすべきである.  同一内容であれば,同じ名前のマクロを複数定義してもよ い.(異なっていればコンパイルエラー.)  置換内容のない名前も定義できる. #define DEBUG#define DEBUG  末尾にセミコロンをつけない. #define WORD_SIZE 6;#define WORD_SIZE 6; は(たいていの場合)間違 い.

9 関数形式マクロ(1) () オブジェクト形式マクロとほぼ同じ書式. 置換対象に「 (…) 」をつける.  #define pint(x) printf("%d\n",x) pint(a+1);printf("%d\n", a+1);  #define pint(x) printf("%d\n",x) に対して, pint(a+1); は printf("%d\n", a+1); に置き換え られる.  複数の引数をとることもできる.そのときは,置換対象の 各引数の間にカンマを入れる.  カッコ内に何も書かなければ,引数なしの関数形式マクロ が定義される.

10 関数形式マクロ(2) 注意点  単純に置き換える. #define mul(x, y) x*y z=mul(6+1,2); #define mul(x, y) ((x)*(y))#define mul(x, y) x*y に対して, z=mul(6+1,2); としたとき, z=14 ではなく z=8 とな る. ⇒ #define mul(x, y) ((x)*(y)) のように,置 換内容の引数と,置換内容全体にカッコをつける.  置換対象に引数を2箇所以上書くことができる.このとき, その回数だけ置換される. #define triple(x) ((x)+(x)+(x)) b=triple(++a); b=((++a)+(++a)+(++a));#define triple(x) ((x)+(x)+(x)) に対して b=triple(++a); と書くと, b=((++a)+(++a)+(++a)); となる.

11 関数形式マクロ(3) # 引数 置換内容の中で「 # 引数」と書くと,引数を文字列にで きる.  #define pint(x) printf(#x " = %d\n", x) pint(a+1);printf("a+1" " = %d\n", a+1);  #define pint(x) printf(#x " = %d\n", x) に対し て pint(a+1); は printf("a+1" " = %d\n", a+1); に置き換えられる.  通常の関数定義では,変数名を 引数にとってその文字列を得る ことはできない. 「文字列リテラルの連 結」により,これは printf("a+1 = %d\n", a+1); と同じとなる.

12 関数か関数形式マクロか 関数 … 「機能」を正確に表現したいとき int square_int(int x) { return x * x; }  例: int square_int(int x) { return x * x; }  引数や戻り値の型に制約される.  関数呼び出しのオーバーヘッドがある.  ローカル変数や制御文を活用できる.  実引数が ++a などのときも,その評価は一度だけ. マクロ … 「機能」を簡便に表現したいとき #define square_int(x) ((x) * (x))  例: #define square_int(x) ((x) * (x))  引数や評価式に型はない.  (狭義の)コンパイル前に展開され,オーバーヘッドは少 ない.  ローカル変数や制御文は使用しにくい.  (マクロ利用側の)引数は,置換内容の回数だけ評価され る.

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

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

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

16 他のファイルの取り込み #include #include  ライブラリ関数などが宣言されているファイルを取り込む (インクルードする). #include " ファイル名 " #include " ファイル名 "  自作のファイルを取り込む.

17 ヘッダファイル 関数プロトタイプ,構造体や特殊な型,定数などが宣 言・定義されているファイル.  #include  #include とすると, /usr/include/stdlib.h を取り込む(ヘッダファイ ルの所在は処理系依存).  ヘッダファイルの中で,他のヘッダファイルをインクルー ドすることもよく行われる. 慣例として  ファイル名を「.h 」で終わらせる.  関数は,「宣言」のみして「定義」はしない.  同一ファイルに対する複数回のインクルードがあっても, 2回目以降は処理しないようにする.

18 関数プロトタイプ (Function prototype) 型名 関数名 ( 引数の型の並び ); 構文 : 型名 関数名 ( 引数の型の並び );  「引数の型の並び」は,「引数(型と変数)の並び」でも よい.このとき変数名は無視される.  一般に,グローバル区間に記述する. int swapcase(int);  例 : int swapcase(int); 関数プロトタイプを用いることで, 順番を気にすることなく  関数定義の順番を気にすることなくプログラムを記述でき る. ただし,関数プロトタイプは,関数定義の前に書くこ と.  関数の入出力が明確になる. セミコロンを忘れず に 「関数原型」 ともいう

19 ヘッダファイルとライブラリ関数 既に定義されている関数や定数を利用するには,あらか じめ,適切なヘッダファイルをインクルードしなければ ならない.  printf#include  printf なら #include  NULL#include  NULL なら #include が一般的. インクルードすべきヘッダファイル名は, manpage で 知ることができる.  man 3 printf  jman 3 printf  JM Project (

20 英字大小変換プログラム(1) 仕様  コマンドライン引数の各語の英字の大小を変換する. 例 ./upcase Wakayama Univ. WAKAYAMA UNIV. ./downcase Wakayama Univ. wakayama univ. ./swapcase Wakayama Univ. wAKAYAMA uNIV. 一つのプログラムファイル (upcase.c) から,3つの実 行ファイル (upcase,downcase,swapcase) を作る.

21 英字大小変換プログラム(2) 1文字ごとの変換  ライブラリ関数を使用する. tolower 大 → 小 : tolower toupper 小 → 大 : toupper  関数形式マクロを用いて upcase と downcase も定義して おく.  swapcase は関数で定義するのが自然. 文字列ごとの変換  main 関数の中で,2重ループにより処理する. 外側の for は,コマンドライン引数を順番に見る. 内側の while は,文字列を 1 文字ずつ見る. これらは自作しよう と思わないこと

22 英字大小変換プログラム(3) 「ひとつのプログラムファイルから,3つの実行ファイ ルを作る」方法  make upcase  ln -s upcase downcase  ln -s upcase swapcase コマンド名に特定の文字列が含まれていれば, upcase 関数に代えて, downcase または swapcase の関数を呼 び出す. argv[0]  コマンド名は, argv[0] . strstr  文字列が含まれているかのチェックには,ライブラリ関数 の strstr を用いる.ここでは has_string 関数を(関数 形式マクロで)定義している. ファイル downcase が作 られ,これはファイル upcase のシンボリックリ ンクとなる.

23 有用なライブラリ関数(1) #include #include を必要とするもの putchar  int putchar(int c) … 1 文字出力 #include #include を必要とするもの atoi  int atoi(char *s) … 文字列から整数値への変換 exit  void exit(int status) … プログラムの終了 rand  int rand(void) … 乱数生成 #include #include を必要とするもの strlen  size_t strlen(char *s) … 文字列の長さ strcmp  int strcmp(char *s1, char *s2) … 2つの文字列を比 較 strstr  char *strstr(char *s1, char *s2) … 文字列検索

24 有用なライブラリ関数(2) #include #include を必要とするもの isdigit  int isdigit(int c) … 文字が数字であるか判定 tolower  int tolower(int c) … 大文字を小文字に変換 toupper  int toupper(int c) … 小文字を大文字に変換 #include #include を必要とするもの exp  double exp(double x) … e の x 乗 floor  double floor(double x) … x 以下で最大の整数

25 まとめ 前処理指令と関数プロトタイプをうまく使えば,人間に とって読みやすいプログラムを書くことができる. ライブラリ関数を使うには, #include を用いて適切な ヘッダファイルをインクルードする. 前処理は,コンパイルの前に行われる.そのため書式は C の文法と異なる.

26 次に学ぶこと:ファイル処理(1) UNIX の中での「ファイル」  UNIX では,すべての入出力はファイルを読み書きするこ とによって行われる.キーボードや画像でさえも,ファイ ルシステム上のファイルである.(『プログラミング言語 C 』一部改変) C プログラミングの中での「ファイル」  プログラムが終了しても,内容が保持されるデータ構造. 比較:オブジェクトは, auto 変数, static 変数, ヒープ領域の変数のいずれも,プログラム終了時に破 棄される. 「ストリーム」を介して,バイト列として読み書き可 能.

27 次に学ぶこと:ファイル処理(2) 問題  ファイルを入力にとり,先頭に行番号をつけて出力でき る?  標準入力(キーボードなど)からの入力に対して,先頭に 行番号を右揃えでつけて出力できる?