K&R演習[1-18]

課題

各入力行から、行の後ろのブランクやタブを取り除き、かつ空白行は全て削除するようなプログラムを書け。

回答

#include <stdio.h>
#include <limits.h>
#include <string.h>

#define MAX_LINE_NUM    1000        /* 入力行数の最大値 */
#define MAX_LENGTH      1000        /* 入力文字列長の最大値 */
const int MIN_COPY_LENGTH = 80;     /* コピーする最低文字列長 */

const char TRUE = 1;
const char FALSE = 0;

typedef unsigned long long u8;

int getline(char line[], u8 maxline);
char copy(char to[], char from[]);


/**
 * @fn      Main
 * @brief
 * @param
 * @return
 * @detail
 */
int main(void)
{
    u8 i, len, num_line = 0;        // 行数
    char line1[MAX_LENGTH];                 // 保存元(読み取った文字列)
    char line2[MAX_LINE_NUM][MAX_LENGTH];   // 保存先

    while ((len = getline(line1, MAX_LENGTH)) > 0) {

        if (copy(line2[num_line], line1) == TRUE) {;    // 保存元から保存先へコピー
            num_line++;                                 // 有効な行なら次の行へ
        }
        if (num_line >= MAX_LINE_NUM) {     // 保存先の行数を使い切ったら終了
            break;
        }
    }

    printf("\n --- copy --- \n");           // タイトル
    for (i = 0; i < num_line; i++) {        // 保存した行数だけ
        printf("%s", line2[i]);             // 保存先から取り出して印字
    }
    return 0;
}

/* getline: sに行を入れる */
int getline(char s[], u8 lim)
{
    int c;
    u8 i;
    char flg = FALSE;

    for (i = 0; (i < lim - 1) && ((c = getchar()) != EOF) && (c != '\n'); ++i) {
        if (c == '.') {     // コロンを発見したら
            flg = TRUE;     // 発見フラグをONする
        }
        if ((flg == FALSE) ||   // コロン発見前または
            (c != ' ') ||   // スペースではない、または
            (c != '\t')) {  // タブでもなければ
            s[i] = c;       // コピーする
        }
    }

    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

/* 行コピーする */
char copy(char to[], char from[])
{
    u8 i;
    char flg = FALSE;

    i = 0;
    while ((to[i] = from[i]) != '\0') {
        if ((from[i] != ' ') &&
            (from[i] != '\n') && 
            (from[i] != '\t')) {
            flg = TRUE;
        }

        ++i;
    }
    return flg;
}

実行内容

There we have none.

This is my uncle .


The only advice I can give is ...

実行結果

--- copy ---
There we have none.
This is my uncle .
The only advice I can give is ...

補足

「行の後ろのブランク」を、ピリオド以降のタブと空白と解釈した。