サイトマップ / 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言語講座−それ自体コンパイルできる教材を使った講座です−

青い直線

サイトマップ / C言語講座出入り口総目次目次:ファイル>英文字の出現頻度||デモ用