サイトマップ / C言語講座>出入り口>総目次>目次:ファイル>英文字の出現頻度||デモ用
[印字可能な文字の数を数える]←このソース→[長さが一定のレコード]
/* 今日は、テキストファイルを開いて、ファイル中の英文字の出現頻度を調べます。まず最初にこのファイルを開いて、ファイル名を"Filex.txt"に変えて、コンパイル済みのプログラムと同じフォルダに置いて下さい。
ストリーム ( stream ) とは、プログラムが文字を読み書きする対象のことです。例えば、コンソールは stdout、キーボードは stdin、今回のソースプログラムでは、ファイル fp です。
メインルーチンの中に、下記の表現があります。
if ((fp = fopen("filex.txt", "r")) == NULL) {
Cでは、よくこういう表現法を使います。fopen("filex.txt", "r") は、filex.txt というファイルを、読み込み専用ストリームで開くということです。標準ライブラリ関数 fopen( ) を呼び出して、ファイルを開くことに成功すると、開いたファイルに対するポインタが返ってきます。それを、fp に代入します。以後のそのファイルに対する操作は、fp を通して行います。
(fp = fopen("filex.txt", "r")) == NULL は、ファイルを開くのに失敗した時、真となり、{ } 内が実行されます。
stderr は、プログラムが起動した時に、stdout および stdin と供に自動的に開く、バッファリングしない書き込み専用ファイルです。
英文字の出現頻度をカウントする関数を下記に示します。
void CountLett(FILE *fp) { int c; while ((c = getc(fp)) != EOF) if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') alpha[c]++; }
while ((c = getc(fp)) != EOF) では、getc(fp) が fp の指すファイルから、1文字読み込みます。成功すればその値を、c に代入します。ファイルの終末に達すると、読み込みに失敗して、EOF が返ってくるので、while ループから抜けます。
if ( ) のカッコの中で、c の値を調べています。
c >= 'a' && c <= 'z' は、c が英小文字の時、真になります。 c >= 'A' && c <= 'Z' は、c が英大文字の時、真になります。
従って、if の次の行は、c が英文字の時実行されます。
if ( ) のカッコの中の関係演算子について、検討します。
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
'&&' の方が演算の優先順位が高いので、カッコで '||' の左右の式を括る必要はありません。'||' があると、その左側から先に評価されることが、Cでは保障されています。
上記のコードでは、c が小文字かどうかを先に調べます。大文字より小文字が多い場合、小文字かどうかを先に調べた方が実行速度が速くなります。大文字の方が多いファイルを扱うなら、大文字かどうかを先に調べます。
alpha[ ] は、要素を BYTE 個持つ、int 型の配列です。関数の外側で定義しているので、どの関数からでも、読み書きできます。実行時にメモリに割り付けられる自動変数と異なり、コンパイル時に0に初期化されます。プログラムの実行中常にメモリに存在し続けます。
文字は値を持っています。c の取りうる値の範囲は、アスキーコードの範囲になります。c がアルファベットなら、アスキーコード表で、'a' から 'z' と'A' から 'Z' の所に書いてある値です。
alpha[ ] は int 型の配列です。alpha[c] は配列の添字の値が、'c' に代入された文字の値になっている要素です。alpha[c]++では、その要素の値をインクリメントします。
以上の操作をファイルの終わりまで行うと、ファイルの中のアルファベットの各文字の出現頻度が、alpha[ ] に保存されます。PrintResult( ) はそれを画面に出力します。詳細は、ソースプログラム中のコメントを読んで下さい。"Filex.html" を"Filex.txt"に変更し、同じホルダーに置いてから、実行して下さい。 */
#include <stdio.h> #include <stdlib.h> /* exit( ) で必要 */ #define BYTE 256 int alpha[BYTE]; /* 関数の外で宣言 */ void CountLett(FILE *fp); void PrintResult(void) ; void main(void); /* ファイル中の英文字の出現頻度を調べる */ void CountLett(FILE *fp) { int c; /* ファイルの終わりに達するまで1文字読み込む */ while ((c = getc(fp)) != EOF) /* c がアルファベットの小文字か大文字なら */ if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') alpha[c]++; /* カウントする */ } void PrintResult(void) { int c; for (c = 'a'; c <= 'z'; c++) /* 小文字の出現頻度を */ printf("%c:%d\t", c, alpha[c]); /* 表示 */ printf("\n\n"); for (c = 'A'; c <= 'Z'; c++) /* 大文字の出現頻度を */ printf("%c:%d\t", c, alpha[c] ); /* 表示 */ printf("\n"); } void main(void) { FILE *fp; if ((fp = fopen("Filex.txt", "r")) == NULL) { /* ファイルを開けなければ */ /* メッセージを表示して */ fprintf ( stderr, "Can't Open C Source File!\n" ); exit (2); /* 終了 */ } printf("filex.txt ファイルにおけるアルファベットの出現頻度\n"); CountLett(fp) ; /* 文字の出現頻度を調べて */ PrintResult( ); /* 表示する */ fclose(fp); /* ファイルを閉じる */ } |
/* ソート ( データをある規則に則って並べ替える ) という言葉が、一度も出ていませんが、今回は、ファイルの中に出現する英文字を昇順にソートしたことになります。今回使っているアルゴリズムは、ビンソートといいます。色々なソート法を紹介する時に、詳しく説明します。 */
[印字可能な文字の数を数える]←このソース→[長さが一定のレコード]
/* (C) 2000- YFプロ. All Rights Reserved. */ 提供:C言語講座−それ自体コンパイルできる教材を使った講座です−