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

スポンサーリンク

鍛錬 299

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

カッコ,中カッコ,大カッコのつりあいがとれていないといったプログラムの基本的な構文エラーのチェックを行なうプログラムを書け。引用符・2重引用符・コメントなどの処理も忘れないこと。(このプログラムを完全に汎用的にしようとすると,これを書くのは難しくなる。)

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

スポンサーリンク

プログラム

以下は、プログラムに記述されているカッコ,中カッコ,大カッコのつりあいを確認するプログラム、kr_1_24.c です。

// include
#include <stdio.h>

// preprocessor
#define MAX_DATA  51200  // 入力可能な文字数の最大値

#define L_SMALL   0  // 小括弧(左)
#define R_SMALL   1  // 小括弧(右)
#define L_MEDIUM  2  // 中括弧(左)
#define R_MEDIUM  3  // 中括弧(右)
#define L_LARGE   4  // 大括弧(左)
#define R_LARGE   5  // 大括弧(右)

#define SUCCESS  0  // 成功
#define ERROR    1  // エラー

// prototype
int CountData(int count[], int lim);

// main
int main(void)
{
	int count[8];
	int state;
	int len;
	int i;
	
	// 配列初期化
	for (i = 0; i < 8; ++i)
		count[i] = 0;
	
	// 各種括弧の個数を取得
	while ((len = CountData(count, MAX_DATA)) > 0) {
		;
	}
	
	// 状態を初期化
	state = SUCCESS;  // 状態:成功
	
	// 各種括弧のつりあいを確認
	// 小括弧
	if (count[L_SMALL] != count[R_SMALL]) {
		state = ERROR;  // 状態:エラー
		printf("ERROR,小括弧() のつりあいがとれていない\n");
		printf("左 = %d個,右 = %d個\n", count[L_SMALL], count[R_SMALL]);
	}
	// 中括弧
	if (count[L_MEDIUM] != count[R_MEDIUM]) {
		state = ERROR;  // 状態:エラー
		printf("ERROR,中括弧{} のつりあいがとれていない\n");
		printf("左 = %d個,右 = %d個\n", count[L_MEDIUM], count[R_MEDIUM]);
	}
	// 大括弧
	if (count[L_LARGE] != count[R_LARGE]) {
		state = ERROR;  // 状態:エラー
		printf("ERROR,大括弧[] のつりあいがとれていない\n");
		printf("左 = %d個,右 = %d個\n", count[L_LARGE], count[R_LARGE]);
	}
	
	// つりあいがとれている場合
	if (state == SUCCESS) {
		printf("SUCCESS\n");
		printf("小括弧:左 = %d個,右 = %d個\n", count[L_SMALL], count[R_SMALL]);
		printf("中括弧:左 = %d個,右 = %d個\n", count[L_MEDIUM], count[R_MEDIUM]);
		printf("大括弧:左 = %d個,右 = %d個\n", count[L_LARGE], count[R_LARGE]);
	}
	
	return 0;
}

// ==========================================================
// @brief      各種括弧の個数を記録し,データ全体の長さを返す
// @param[out] count  各種括弧の個数を記録
// @param[in]  lim    入力可能な文字数の最大長
// @return     i -> 取得したデータ全体の長さ
// @note       無し
// ==========================================================
int CountData(int count[], int lim)
{
	int c;
	int i;
	
	for (i = 0; i < lim - 1 && (c = getchar()) != EOF; ++i) {
		if (c == '(')
			++count[L_SMALL];
		else if (c == ')')
			++count[R_SMALL];
		else if (c == '{')
			++count[L_MEDIUM];
		else if (c == '}')
			++count[R_MEDIUM];
		else if (c == '[')
			++count[L_LARGE];
		else if (c == ']')
			++count[R_LARGE];
	}
	
	return i;
}
スポンサーリンク

サンプルプログラム

以下は、プログラム kr_1_24.c によって括弧のつりあいを確認されるサンプルプログラム、sample.c です。

#include <stdio.h>

int main(void)
{
	int tmp [8];
	int i;
	
	for (i = 0; i < 8; ++i) {
		tmp[i] = 0;
	}
	
	// コメント1
	printf("1\n");
	
	/* コメント2 */
	printf("2\n");
	
	/*
	コメント3
	*/
	printf("3\n");
	
	return 0;
}
スポンサーリンク

実行結果

以下は、プログラム kr_1_24.c を実行して、サンプルプログラム sample.c に記述されている括弧のつりあいを確認しています。

(サンプルプログラム sample.c のファイル内容を cat で標準出力し、パイプ | を使用して、プログラム kr_1_24.c の getchar() に標準入力として読み込ませています。)

各種括弧 (),{},[] がつりあっている場合

以下は、sample.c 内の各種括弧がつりあっている場合の実行結果です。

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_24.c -o kr_1_24
***@ubuntu:~/***/test/c$ cat ./sample.c | ./kr_1_24
SUCCESS
小括弧:左 = 5個,右 = 5個
中括弧:左 = 2個,右 = 2個
大括弧:左 = 2個,右 = 2個

小括弧 () がつりあわない場合

以下は、sample.c 内(8行目)の for 文について、左側小括弧 ( を削除した場合の実行結果です。

削除前

int tmp [8];
int i;

for (i = 0; i < 8; ++i) {
	tmp[i] = 0;
}
 

削除後

int tmp [8];
int i;

for i = 0; i < 8; ++i) {
	tmp[i] = 0;
}
 

実行結果

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_24.c -o kr_1_24
***@ubuntu:~/***/test/c$ cat ./sample.c | ./kr_1_24
ERROR,小括弧() のつりあいがとれていない
左 = 4個,右 = 5個

中括弧 {} がつりあわない場合

以下は、sample.c 内(8行目)の for 文について、左側中括弧 { を削除した場合の実行結果です。

削除前

int tmp [8];
int i;

for (i = 0; i < 8; ++i) {
	tmp[i] = 0;
}
 

削除後

int tmp [8];
int i;

for (i = 0; i < 8; ++i)
	tmp[i] = 0;
}
 

実行結果

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_24.c -o kr_1_24
***@ubuntu:~/***/test/c$ cat ./sample.c | ./kr_1_24
ERROR,中括弧{} のつりあいがとれていない
左 = 1個,右 = 2個

大括弧 [] がつりあわない場合

以下は、sample.c 内(9行目)の配列 tmp について、左側大括弧 [ を削除した場合の実行結果です。

削除前

int i;

for (i = 0; i < 8; ++i) {
	tmp[i] = 0;
}

// コメント1

削除後

int i;

for (i = 0; i < 8; ++i) {
	tmp i] = 0;
}

// コメント1

実行結果

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_24.c -o kr_1_24
***@ubuntu:~/***/test/c$ cat ./sample.c | ./kr_1_24
ERROR,大括弧[] のつりあいがとれていない
左 = 1個,右 = 2個
タイトルとURLをコピーしました