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

スポンサーリンク

鍛錬 179

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

「各入力行から、行の後のブランクやタブを取り除き、かつ空白行はすべて削除するようなプログラムを書け」という問題です。
 
プログラム

以下は、各入力行から、行の後のブランクとタブを取り除き、かつ空白行はすべて削除するプログラム kr_1_18.c です。

// include
#include <stdio.h>

// preprocessor
#define MAXLINE 1000

// prototype
int my_getline(char line[], int maxline);
void copy(char to[], char from[]);
int RemoveEndOfLineOfBlankAndTab(char line[], int len, char edit_line[]);

// main
int main(void)
{
	int len;
	int ret;
	int i;
	char line[MAXLINE];       // 編集前の行
	char edit_line[MAXLINE];  // 編集後の行
	
	i = 1;
	while ((len = my_getline(line, MAXLINE)) > 0) {
		// 入力した行を編集
		ret = RemoveEndOfLineOfBlankAndTab(line, len, edit_line);
		len = ret;
		
		printf("----- %d 回目 -----\n", i);
		printf("入力行の長さ = %d\n", len);
		printf("入力行のテキスト = %s", edit_line);
		if (len != 0)
			printf("\n");
		else
			printf("\n\n");
		++i;
	}
	
	return 0;
}

// =====================================
// @brief      行を取得し,その長さを返す
// @param[in]  lim  入力行の最大長
// @param[out] s    取得した行
// @return     i -> 取得した行の長さ
// @note       無し
// =====================================
int my_getline(char s[], int lim)
{
	int c, i;
	
	for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
		s[i] = c;
	if (c == '\n') {
		s[i] = c;
		++i;
	}
	
	s[i] = '\0';
	
	return i;
}

// ===================================
// @brief      文字列をコピーする
// @param[in]  from  コピー元の文字列
// @param[out] to    コピー先の文字列
// @return     無し
// @note       無し
// ===================================
void copy(char to[], char from[])
{
	int i;
	
	i = 0;
	while ((to[i] = from[i]) != '\0')
		++i;
}

// ================================================================
// @brief      行の後にブランクまたはタブが存在する場合は取り除く.
// @brief      行が空白行の場合は削除する.
// @brief      編集後の,行の長さを返す.
// @param[in]  line       編集前の行
// @param[in]  len        編集前の,行の長さ
// @param[out] edit_line  編集後の行
// @return     edit_len -> 編集後の,行の長さ
// @note       無し
// ================================================================
int RemoveEndOfLineOfBlankAndTab(char line[], int len, char edit_line[])
{
	int array_null;  // 配列において,'\0'が格納されている要素番号
	int edit_len;    // 編集後の,行の長さ
	int c;
	int i;
	
	// 配列において,'\0'が格納されている要素番号を格納
	array_null = len;
	
	// 編集用の配列にコピー
	copy(edit_line, line);
	
	// 空白行の場合
	c = edit_line[0];
	if (c == ' ' || c == '\t') {
		// 削除
		edit_line[0] = '\0';
		
		// 行の長さを0に設定
		edit_len = 0;
		
		return edit_len;
	}
	
	// 行の最後尾から検索
	for (i = len; i > 0; --i) {
		c = edit_line[i];
		
		// ブランクまたはタブの場合
		if ((c == ' ') || (c == '\t')) {
			edit_line[i] = '\n';
			++i;
			edit_line[i] = '\0';
			array_null = i;
			--i;
		}
		// 改行でもなく'\0'でもない場合
		else if ((c != '\n') && (c != '\0'))
			break;
	}
	
	// 行の長さを格納
	edit_len = array_null;
	
	return edit_len;
}

 
実行結果

以下は、プログラム kr_1_18.c を実行し、次に示す順序で文字列を入力しています。

※ 結果として表示される入力行の長さは、改行コードも含みます。

  1. ABCDE を入力してエンターキーを押下
  2. ABCDE の後に スペース を入力してエンターキーを押下
  3. ABCDE の後に タブ を入力してエンターキーを押下
  4. 文字を入力せずに、エンターキーを押下(改行のみを入力)
  5. スペース のみを入力してエンターキーを押下(空白行)
  6. タブ のみを入力してエンターキーを押下(空白行)
***@ubuntu:~/***/test/c$ 
***@ubuntu:~/***/test/c$ gcc -Wall -Wextra kr_1_18.c -o kr_1_18
***@ubuntu:~/***/test/c$ ./kr_1_18
ABCDE 
----- 1 回目 -----
入力行の長さ = 6
入力行のテキスト = ABCDE

ABCDE 
----- 2 回目 -----
入力行の長さ = 6
入力行のテキスト = ABCDE

ABCDE	
----- 3 回目 -----
入力行の長さ = 6
入力行のテキスト = ABCDE


----- 4 回目 -----
入力行の長さ = 1
入力行のテキスト = 

 
----- 5 回目 -----
入力行の長さ = 0
入力行のテキスト = 

	
----- 6 回目 -----
入力行の長さ = 0
入力行のテキスト =

 
上記に示した通り、2 回目(行の後がスペース)と 3 回目(行の後がタブ)の入力では、行の後のブランクまたはタブが削除されています。

また、5 回目と 6 回目の入力(空白行の入力)では、行が削除されています。

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