C言語ケーススタディ ファイルの行数・単語数をカウントするプログラム2




2014年10月より個人の方を対象に、Study C無料提供を開始しました。
C言語を勉強中の方は、学習・教育に最適なC言語インタープリタのStudy Cを使ってみてください(個人の方は無料です)。
大学・高専・高校などの教育機関での採用実績も多数あるロングセラー商品Study Cが、個人向けに無料提供を始めました。
インタープリタの手軽さに加え、ゲームや3Dタートルグラフィックで楽しく勉強したりと、C言語の学習を強力にサポートします。
ブロック崩しゲーム 3Dツリー クリスマスツリー
また、このようなボタンの用意されているページでは、掲載しているプログラムをStudy Cに直接ロードし実行したりすることができます。
Study Cにロードする Study Cにロードし編集する Study Cにロードし実行する
Study C無料利用についての詳細は、このページを参照してください。



前回のプログラムは一つのファイルを指定して行数・単語数をカウントするプログラムでしたが、通常のwcコマンドは複数のファイルやワイルドカードでファイルを指定することができます。 今回は、複数のファイルをコマンドラインから指定できるように変更します。

変更点は次のとおりです。
(1)ファイルの読み込みとカウントを行う部分を別関数(WordCount)として分離します。
(2)WordCount関数にはカウントするファイル名を指定します。
(3)WordCount関数に渡されたファイル名(パス名)のファイル部分だけ(最後の'\'文字よりうしろ)表示するように変更します。
(4)指定したファイル全体の合計を最後に表示するためにtotal_c、total_w、total_lの3個のグローバル変数を用意し行数などを加算していきます。
(5)main関数はargcの個数-1だけループでargv[]の内容をWordCount関数に渡して処理させます。

注)このプログラムはパス名からファイル名を取り出す部分でstrrchr()関数を使用しているので全角文字のファイル名やディレクトリ名では正常に動作しません。
strrchar()関数を_mbsrchr()関数に変更すれば正しく動作します(単純に関数名を置き換えれば正しく動作するようになります - Study C以外では適切なインクルードファイルの指定も必要です)。 詳しくは、_mbsrchr()関数を参照してください。

#include <stdio.h>

unsigned long
        total_c, total_w, total_l;

int     WordCount(char *fname);

void    main(int argc, char *argv[])
{
        int        i1;

        if(argc < 2){
                printf("コマンドの入力形式が間違っています.\n");
                return;
        }

        total_l = total_w = total_c = 0;
        for(i1 = 1; i1 < argc; i1++){
                if(WordCount(argv[i1]) == 0){
                        return;
                }
        }

        printf("%7ld %7ld %7ld TOTAL\n", total_l, total_w, total_c);
}


WordCount(char *fname)
{
        FILE    *fp;
        char    buff[1024], *ptr;
        int     len;
        unsigned char
                *file,
                *line_buff,
                *wp;
        int     i1, num, blank;
        long    character,word,line;

        fp = fopen(fname, "r");
        if(fp == NULL){
                printf("ファイルがオープンできません[%s].\n", fname);
                return(0);
        }

        blank = 0;
        character = word = line = 0;
        while((num = fread(buff, 1, 1024, fp)) > 0){
                for(wp = buff; num > 0; num--,wp++){
                        if(*wp <= ' '){
                                if(*wp == '\n'){
                                        line++;
                                        character++;
                                }
                                if( !blank )
                                        word++;
                                blank = 1;
                                character++;
                        }
                        else{
                                blank = 0;
                                character++;
                        }
                }
        }
        total_l += line;
        total_w += word;
        total_c += character;

        ptr = strrchr(fname, '\\');
        if(ptr == NULL)
                ptr = fname;

        printf("%7ld %7ld %7ld %s\n", line, word, character, ptr);
        fclose(fp);
        return(1);
}

このプログラムは"run file1 file2 file3"といった形式で実行することができます。 UNIX環境で使用するプログラムならばこのプログラムでワイルドカード("wc *.c")を使用することができます(シェルがワイルドカードを展開してくれます)。 DOSやWindowsではワイルドカードが展開されずに渡されてくるので、このプログラムでは使用することができません。 ワイルドカードの展開については次回説明します。