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

スポンサーリンク

鍛錬 295

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

Cプログラムからすべてのコメントを除去するプログラムを書け。引用符で囲まれた文字列や文字定数を正しく扱うことを忘れないこと。Cのコメントは入れ子になっていない。

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

スポンサーリンク

プログラム

以下は、プログラムから全てのコメントを除去するプログラム、kr_1_23.c です。

// include
#include <stdio.h>

// preprocessor
#define MAX_DATA   51200  // 入力可能な文字数の最大値
#define NOT_EXIST  0      // 存在しない
#define EXIST      1      // 存在する

// prototype
int GetData(char data[], int lim);

// global
char data[MAX_DATA];  // ファイルデータ

// main
int main(void)
{
	int len;
	
	// データを取得して表示
	while ((len = GetData(data, MAX_DATA)) > 0) {
		printf("%s", data);
		printf("\n");
	}
	
	return 0;
}

// ===========================================
// @brief      データを取得し,その長さを返す
// @param[out] data  取得したデータ
// @param[in]  lim   入力可能な文字数の最大長
// @return     i -> 取得したデータの長さ
// @note       無し
// ===========================================
int GetData(char data[], int lim)
{
	int c;
	int i, n;
	int slash_flag;     // '/'存在フラグ
	int asterisk_flag;  // '*'存在フラグ
	
	// 存在フラグを初期化
	slash_flag = NOT_EXIST;     // '/'が存在しない
	asterisk_flag = NOT_EXIST;  // '*'が存在しない
	
	for (i = 0; i < lim - 1 && (c = getchar()) != EOF; ++i) {
		// '/'または'*'の場合
		if (c == '/' || c == '*') {
			// 前回が'/'であった場合
			if (slash_flag == EXIST) {
				// 今回'/'を取得した場合(// が成立)
				if (c == '/') {
					// コメントが終了するまでループ
					for (n = i; n < lim - 1 && (c = getchar()) != EOF; ++n) {
						// 改行コードの場合(コメント終了) break
						if (c == '\n') {
							--i;
							data[i] = c;
							break;
						}
					}
				}
				// 今回'*'を取得した場合(/* が成立)
				else if (c == '*') {
					// コメントが終了するまでループ
					for (n = i; n < lim - 1 && (c = getchar()) != EOF; ++n) {
						// '/'の場合
						if (c == '/') {
							// */ が成立する場合(コメント終了) break
							if (asterisk_flag == EXIST) {
								// '*'存在フラグを初期化
								asterisk_flag = NOT_EXIST;  // '*'が存在しない
								break;
							}
						}
						// '*'の場合
						else if (c == '*')
							// '*'存在フラグを変更
							asterisk_flag = EXIST;      // '*'が存在する
						else
							// '*'存在フラグを変更
							asterisk_flag = NOT_EXIST;  // '*'が存在しない
					}
					
					i = i - 2;
				}
				
				// '/'存在フラグを初期化
				slash_flag = NOT_EXIST;  // '/'が存在しない
			}
			// 前回が'/'ではない場合
			else {
				data[i] = c;
				
				// '/'存在フラグを変更
				slash_flag = EXIST;  // '/'が存在する
			}
		}
		// '/'または'*'ではない場合
		else {
			data[i] = c;
			
			// '/'存在フラグを初期化
			slash_flag = NOT_EXIST;  // '/'が存在しない
		}
	}
	
	data[i] = '\0';
	
	return i;
}
スポンサーリンク

サンプルプログラム

以下は、プログラム kr_1_23.c によってコメントを除去されるサンプルプログラム sample.c です。

3箇所にコメントが記述されています。

#include <stdio.h>

int main(void)
{
	int result_1;
	int result_2;
	
	result_1 = 9 / 3;
	result_2 = 9 * 3;
	
	// コメント1
	printf("1\n");
	
	/* コメント2 */
	printf("2\n");
	
	/*
	コメント3
	*/
	printf("3\n");
	
	return 0;
}
スポンサーリンク

実行結果

以下は、プログラム kr_1_23.c を実行して、サンプルプログラム sample.c のコメントを除去しています。

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

***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_23.c -o kr_1_23
***@ubuntu:~/***/test/c$ cat ./sample.c | ./kr_1_23
#include <stdio.h>

int main(void)
{
	int result_1;
	int result_2;
	
	result_1 = 9 / 3;
	result_2 = 9 * 3;
	
	
	printf("1\n");
	
	
	printf("2\n");
	
	
	printf("3\n");
	
	return 0;
}

 
上記に示した通り、サンプルプログラム sample.c のコメントを全て除去することができました。

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