情報処理Ⅱ 第7回 2004年11月16日(火)
本日学ぶこと さまざまな「空」 ポインタを使ったプログラミング void型 NULLポインタ ナル文字('\0') 空文 任意型のビットパターン出力 回文判定
「空」とプログラム プログラミングと関係のない「空」の例 Cにおける「空」とは,「それは空である」,「空の…がある」などを明示するための概念 「部屋がない」と「空室がある」は違う. 空集合φ={}と,空集合のみからなる集合{φ}={{}}は違う. Cにおける「空」とは,「それは空である」,「空の…がある」などを明示するための概念
void型 voidは「何もない」や「無効な値」を表す型名 用途 × void x; ○ void *x; ただし,sizeof(void)は0ではなく1 用途 関数が引数や戻り値を持たないことを明示するとき void exit(int status); void procedure(void); 任意のポインタ型を表現するとき void *p; void *malloc(size_t size); プログラムを終了するライブラリ関数.通常,exit(0); もしくは exit(1); のいずれかで呼び出す.
NULLポインタ 空ポインタ定数(null pointer constant)とも呼ばれる. NULLはstdio.hなどで定義されている定数で,例えば,(void *)0 で表現される. キャスト(明示的な型変換)なしで,任意のポインタ型オブジェクトへの代入,任意のポインタ値との比較が可能 例: if ((fp = fopen("/dev/null", "r")) != NULL)
ナル文字 '\0' をナル文字(null character)という. 文字列の末尾につく. ○ '\0' == 0 × '\0' == '0' × '\0' != NULL 文字列の末尾につく. ナル文字は,文字列の字数には数えられないが,char型の1要素分(1バイト分)を占める. 例: #include <strings.h> および char word[] = "abcdef"; のあとで strlen(word) は6. sizeof(word) / sizeof(word[0]) は7.
空文 「式;」を式文という.式文から式を取り除いたものを空文(null statement)という. 用途 'a' 'b' 'c' 'd' 「{}」は,空ブロックと呼ばれる. 用途 for文の初期化,条件,増分の省略 for (;;) ... 反復の処理 for (p = "abcdef"; *p && *p != 'c'; p++) ; 'a' 'b' 'c' 'd' 'e' 'f' '\0' p
まとめ 空ポインタ定数のNULL,ナル文字,空文,void型といった「空(null, empty, void)」の概念がある.
ポインタを使ったプログラミング 任意型のビットパターン出力 学ぶこと:ポインタのキャスト(型変換) 回文判定 学ぶこと:文字列の走査
任意型のビットパターン出力 float f = 40; char *p = (char *)&f; とすると,*p, *(p + 1), ..., *(p + sizeof(float)-1) は,fの「バイトごとの」中身である. 1バイトのビットパターンを求めるプログラムを活用して,バイトごとに出力すればいい! float f : p p+1 p+2 p+3 char *p : は1バイト
ポインタのキャストが必要な理由 float f = 40; としたとき, p1+1 float *p1 : float f : p3+1 char *p2 = &f; は,型が合わない. char *p3 = (char *)&f; とすればうまくいく. float *p1 : p1+1 は1バイト char *p3 : p3+1 float f :
ビットパターン出力 float f = 40; の結果 バイトごとに逆順に出力すると fを-10から10まで変えてみると 00000000 00000000 00100000 01000010 バイトごとに逆順に出力すると 01000010 00100000 00000000 00000000 fを-10から10まで変えてみると
回文判定 仕様 例 入力は,コマンドライン引数から獲得する. コマンドライン引数の各文字列が回文になっていれば「Yes」を,そうでなければ「No」を出力する. 英字の大小を区別する.ASCIIコード以外の文字は使用しない. 例 ./palindrome 12321 123321 noon Noon 12321 : Yes 123321 : Yes noon : Yes Noon : No case-sensitive という
回文判定 左と右から1文字ずつ見て p '1' '2' '3' '4' '\0' q r '1' '2' '3' '\0' 1文字ずつ見ていく操作を 文字列の「走査(scan)」という 左と右から1文字ずつ見て 途中で一致していない箇所があれば,「No」 すべて一致し,参照位置が一致または交差すれば,「Yes」 p '1' '2' '3' '4' '\0' No q r Yes '1' '2' '3' '\0'
ポインタ変数は? char *p = argv[i]; char *q = p; char *r = p + strlen(p) - 1; 文字列走査では固定 char *q = p; 文字列の先頭から始まる 文字列走査により1ずつ増えていく char *r = p + strlen(p) - 1; 文字列の末尾から始まる 文字列走査により1ずつ減っていく
まとめ ポインタ型の値は,キャスト演算子で任意のポインタ型に変換できる. 文字列の走査には,char *型のポインタ変数を活用するとよい.