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); }
改行を表示させなければ随分楽になるんだけど・・・。