K&R 演習1-6 解答 (プログラミング言語C 第2版)

スポンサーリンク

鍛錬 65

K&R 演習1-6 解答 (プログラミング言語C 第2版)

getchar() != EOF という式の値が 0 か 1 であることを確認せよ。

B.W.カーニハン D.M.リッチー 石田晴久 訳 『プログラミング言語C 第2版 ANSI 規格準拠』, (共立出版, 2017), pp.22.

スポンサーリンク

プログラム

以下は、getchar() != EOF という式の値が 0 か 1 であることを確認するプログラム、kr_1_6.c です。

#include <stdio.h>

int main(void)
{
	int c;
	int tmp;
	
	// 無限ループ
	while (1) {
		printf("------------------------------\n");
		
		// tmp に getchar() の値を格納
		// c   に getchar() != EOF の値を格納
		c = ((tmp = getchar()) != EOF);
		
		// getchar() の値を表示
		printf("getchar() の値        = %d\n", tmp);
		
		// getchar() != EOF の値を表示
		printf("getchar() != EOF の値 = %d\n", c);
	}
	
	return 0;
}
スポンサーリンク

getchar() != EOF という式の値が 0 か 1 であることの確認

ASCII コードについて

以下は、ASCII コードについての説明です。

文字コード 10進数表記 16進数表記
A 65 0x41
B 66 0x42
C 67 0x43
改行 LF 10 0x0a

上記のプログラム kr_1_6.c を実行した場合の挙動

キーボードから文字を入力する際、文字の入力後にエンターキーを押下するため、文字だけではなく改行コードの LF(10) も入力されます。

つまり getchar() は、ストリームから文字だけでなく LF(10) も取得するため、上記のプログラム kr_1_6.c では、1文字入力してエンターキーを押下するたびに、while() で2回ループすることになります。

getchar() != EOF の値が 真(1) の場合について

まずは、上記のプログラム kr_1_6.c を実行し、文字 A、B、C を順にキーボードから入力してみます。

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_6.c -o kr_1_6
***@ubuntu:~/***/test/c$ ./kr_1_6
------------------------------
A
getchar() が取得した値 = 65
getchar() != EOF の値  = 1
------------------------------
getchar() が取得した値 = 10
getchar() != EOF の値  = 1
------------------------------
B
getchar() が取得した値 = 66
getchar() != EOF の値  = 1
------------------------------
getchar() が取得した値 = 10
getchar() != EOF の値  = 1
------------------------------
C
getchar() が取得した値 = 67
getchar() != EOF の値  = 1
------------------------------
getchar() が取得した値 = 10
getchar() != EOF の値  = 1
------------------------------

 
上記に示した通り、例えば A を入力した場合、A(65) と LF(10) の両方とも、getchar() != EOF の値は 1 となります。

B を入力しても C を入力しても、数字の 3 を入力しても、値は改行コードの LF(10) と共に 1 となります。

よって、文字 A、B、C を入力した場合、getchar() != EOF は 真(1) であり、問題で指示された「値が 0 か 1 であることを確認せよ」のうち、片方の「値が 1 であること」が確認できました。

「A(65) != EOF」は、真(1)
「B(66) != EOF」は、真(1)
「C(67) != EOF」は、真(1)
「LF(10) != EOF」は、真(1)

getchar() != EOF の値が 偽(0) の場合について

次に、問題で指示された「値が 0 か 1 であることを確認せよ」のうち、もう片方の「値が 0 であること」を確認します。

getchar() != EOF が 偽(0) となる入力を行う必要がありますが、キーボードのアルファベットや数字を押下しても、値は 1 となってしまいます。

そこで、値 0 を取得するために getchar() が EOF を取得するようにします。そうすれば、

EOF != EOF

となるため、偽(0) の値を取得することができるはずです。

以下は、EOF を送る方法を確認するために、stty -a で端末オプションを確認しています。

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ stty -a
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

 
上記に示した通り、eof = ^D; という記述があります。

Ctrl+D を押下すれば EOF が送られ、getchar() が EOF を取得して EOF != EOF となるはずです。

以下は、実際に Ctrl+D を押下して確認しました。

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_6.c -o kr_1_6
***@ubuntu:~/***/test/c$ ./kr_1_6
------------------------------
getchar() が取得した値 = -1
getchar() != EOF の値  = 0
------------------------------

 
上記に示した通り、EOF を送ると getchar() != EOF の値は 0 となりました。

これで、問題の「値が 0 か 1 であることを確認せよ」のうち、もう片方の「値が 0 であること」が確認できました。

「EOF != EOF」は、偽(0)
スポンサーリンク

演習問題1-6 の解答

Ctrl+D を押下して EOF を送れば、getchar() != EOF の値は 0 となる。

それ以外の文字や数字を押下すれば、getchar() != EOF の値は 1 となる。

よって、式 getchar() != EOF の値は 0 か 1 である。

タイトルとURLをコピーしました