Cはもともとシステム記述用の言語なので,文字データの操作を行うことが 多いです。テキスト(文字データ)の入出力はテキストストリームとして 扱われます。人間にとっては文学的に意味がある文章も,コンピュータに とっては『スペースで区切られた文字が,改行文字でつなげられた, なが〜い文字列』としてしか認識されません。そしてファイルの最後には, EOF(End Of File)が入ります。
更にいえば,コンピューター内部では,これらの文字は「アスキー文字 コード」で取り扱われます。例えばAは65,aは97というように(いずれも 10進表記)。だから,文字は,char とともに int でも扱うことができます。 |
ここでは,入出力に二つの関数を使います。これらもstdio.hのライブラリに 入っています。
イン | c=getchar() | 呼ばれると,自動的にcに1文字を代入する。 |
アウト | putchar(c) | 呼ばれると,cの内容を表示する。 |
入力した文字をそのまま出力せよ |
これをプログラムにすると,
main() { 変数cをintと宣言; c=getchar()で一つ文字をとってきてcに代入; while(cがEOFでないなら)終わりでないからループに入る{ putchar(c)で文字cを表示する; c=getchar()で一つ文字をとってきてcに代入; } } |
となります。これは,作成→コンパイル→走らせる→入力待ちになるので 文字を入力→終わりはC-d(これがEOF)を入力。としてやればよいです。
シェルのところでやったリダイレクションを利用すれば,すでに作って
あるファイルを入力として,そのコピーを表示させることもできます。 a.out < filename [return] |
このプログラムは,「c=getchar()で一つ文字をとってきてcに代入」が 2箇所あるのでかっこ悪いですね。そこで次のようにしてやりましょう。
main() { int c; while ( (c=getchar() ) != EOF){ putchar(c); } |
ここで,while の中の内側の括弧 ( c=getchar() ) を忘れないこと。 忘れると getchar()!= EOF が先に行われ,cには0が入るだけでになります。 どんな文字を入力しても0が出力されてしまいます。EOFで始めて1が 出力されるでしょう。おまぬけです。
ここから「カウンター」という概念を導入します。「カウンター」というと 仰々しいですが,要は次のようなものです。
で,ここではカウンターとして,整数の変数 nc を使いましょう。nc とは number of characters です。文字数は getchar() を呼んだ回数と 等しいですから,カウンターを getchar() を呼ぶたびにプラス1してやれば, 文字数を数えることができます。mainの中味です。
変数 ncを整数と宣言; カウンターncを0にリセット; while(とってきた文字がEOFでないなら)ループに入る カウンターncをプラス1; 結果(カウンターncの値)をプリントアウト; |
ここで,++ncというのは,nc = nc + 1 と同じことであり,nc の値を 1増やしてから値を使用する(前置演算子)ということです。 似たようなものに後置演算子 nc++( nc の値を使用してから値を1増やす) があります。ここでは,前置演算子のみを使います。細かい事を いわなければ,どちらも『変数nc の値を1増やす』という意味です。
for文で書くこともできます。
whileや for文は,ループに入る前で(式)のテストが行われます。
ループの後でテストするものにはdo....while文があります。これは 最低1回ループが実行されます。 |
行数を数えるということは,改行文字を数えるということです。'\n' と 行数は1対1対応していますから……。getchar()で文字を一つづつとってきて, '\n'が来たときだけカウンターをプラス1してやればよいのです。今度の カウンターは nl (number of lines)です。
変数 nlを整数と宣言; カウンターnlを0にリセット; while(とってきた文字がEOFでないなら)ループにはいる もし(cが'\n'と等しい)ならば カウンターnlをプラス1; 結果(カウンターnlの値)をプリントアウト; |
これが教科書のプログラムです。ただし,改行を一度もいれずにEOFになった 場合は行数0が出力されます。これは望ましくないので,実用的にはちょっと 改良する必要があります。
ちなみに,たとえば,文書中のeの文字の数を数えたいときには
if (c == '\n') を if (c == 'e') と変えるだけでよいので,このプログラムは
文字の出現頻度を調べるのにも使えます。 さらに文字コードも使用できます。'e'なら101だから,if (c==101)でも 同じです。 |
入力したテキストの文字数,行数,単語数を数えるプログラムを 書け |
これは,よくばったプログラムです。でも出来たなら,役に立ちます。
文字や行の数を数えることはすでにやりましたが,単語の数はどう数えよう。
このような問題に対した時はまず,『単語とは何か』というふだん
アタリマエと考えていることから定義する必要があります。
コンピューターは,融通がききません。
ここでは,単語を『空白,タブ,改行を含まない任意の文字列(つまり,
空白,タブ,改行で区切られた文字列ということ)』と定義します。著者は,
「単語の外」と「単語の中」というものを考えました。
外 | 中 | 中 | 中 | 中 | 外 | 中 | 中 | 外 | 中 | 外 | 中 | 中 | 中 | 中 | 外 | 外 | 中 |
T | h | i | s | i | s | a | p | e | n | . | W |
普通の文字なら「状態は単語の中」,スペースやタブや改行なら「状態は 単語の外」というわけです。単語数のカウンター nw (number of words) は, 『状態が「外」から「中」に入った時』だけにプラス1してやれば良いのです。 「外」から「外」,「中」から「中」のときは,無視すればよろしい。
{ 全てのカウンターnc, nl, nw, を0にリセット; まず,状態(stete)を外にしておく(OUT); while(とってきた文字cがEOFでないなら)ループにはいる 文字数カウンタncをプラス1; もし(cが'\n'と等しい)ならば 行数カウンタnlをプラス1; もし(cが' 'か'\n'か'\t'のどれかと等しい)ならば 状態を『単語の外』にして,はじめにもどる; そうでなくて,もし(今の状態が『単語の外』)ならば{ 状態を『単語の中』に変えて; 文字数カウンタnwをプラス1; } 結果(カウンタの値)をプリントアウト } |
どこから手をつけたら良いか分からない問題でも,『単語の外』『単語の中』と いう概念を導入することによって解決することが出来ます。
もっと簡便なもので良ければ,『空白,タブ,改行の数を数えてそれに1を足す プログラム』でもいいのですが(不完全だけどね)。ある問題に対して,それを 解決するプログラムは一つではありません。 |
前にもちょっと出てきましたが,ここで,条件判断文( if 文)が出てきました。 書式は,
もちろん,論理式「かつ(and;&&)」と「または(or;||)」については, ここでは説明はしません。こんなのは当たり前ですからね!