K&Rを読もう(6) 演習 1-8 - 1-12 空白をゴニョゴニョ

ソースが長くなってしまうので普通にやろう。

演習 1-8

空白とタブと改行を数える。

なんとなくenumが使いたくなったので、enumを使用する。

#include <stdio.h>
#include <stdlib.h>

enum {WHITE , TAB, BREAK};

int main(void)
{
    int c;
    int count[BREAK + 1] = {0, 0, 0};

    while ((c = getchar()) != EOF) {
        switch (c) {
        case ' '  : ++count[WHITE]; break;
        case '\t' : ++count[TAB]; break;
        case '\n' : ++count[BREAK]; break;
        }
    }
    printf("white space : %d\n", count[WHITE]);
    printf("tab         : %d\n", count[TAB]);
    printf("break       : %d\n", count[BREAK]);

    exit(EXIT_SUCCESS);
}

メモ。enumは0から始まる。

演習 1-9

二つ以上の空白を一つの空白に置き換えながら、入力を出力。

むむ・・・ちと考えた。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int c, d = '0';
    
    while ((c = getchar()) != EOF) {
        if (!(c == ' ' && d == ' '))
            putchar(c);
        d = c;
    }

    exit(EXIT_SUCCESS);
}

dに前の文字を入れておいて、空白の連続を検出する。最初のd = '0'はダミー。

% ./ex-1-9
Hello       ,       K&R         World   !!
Hello , K&R World !!

SICP読んでて良かった。

演習 1-10

タブを\t,バックスペースを\b,バックスラッシュを\\に変換する。

問題は簡単。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int c;

    while ((c = getchar()) != EOF) {
        switch (c) {
        case '\t' : printf("\\t"); break;
        case '\b' : printf("\\b"); break;
        case '\\' : printf("\\\\"); break;
        default : putchar(c); break;
        }
    }

    exit(EXIT_SUCCESS);
}

問題は"バックスペース"の入力。どうやってやるんだ〜(汗

% ./ex-1-10
^H      \
\b\t\\

C-hでいけました(ふぅ

バックスペースにC-h使ってたらカッコいいと思う。←使ってない人

演習 1-11

wcのバグを暴け。

最後に改行が無いと、行数がカウントされない。

% ./wc
not braak line. 0 3 15

バグの修正は、

int d = '0'
...(略
while(...) {
     ...(略
     d = c;
}
if (d != '\n')
      nl++;

cにはEOFが入っているので、その前の文字を検出しなければならない。めんどい。

最後を改行で終わらせるのはUNIX系OSの常識らしいので、バグじゃなくて仕様と割り切る手もある。

演習 1-12

単語を1行づつ表示する問題。

「フラグを使わないで」としたら結構しんどかった。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main(void)
{
    int c;
    
    while ((c = getchar()) != EOF) {
        if (isspace(c)) {
            putchar('\n');
            while(isspace((c = getchar())))
                ;
            if (c == EOF)
                break;
        }
        putchar(c);
    }

    exit(EXIT_SUCCESS);
}

改行を表示させなければ随分楽になるんだけど・・・。

まとめ

小さなプログラムをたくさんやると力になりそうな気がする。色々なやり方を試していきたい。

K&RSICPのバイブル同時読みはなかなかいい感じ。