C言語関係掲示板

過去ログ

No.211.ファイルの行数を取得したい


No.1307

開いたファイルの行数取得について教えてください。
投稿者---sato(2002/03/24 11:10:29)



はじめまして,satoといいます。
早速ですが,ファイルを読み込んで,そのファイルの行数を取得したいの
ですが,うまくいきません。

以前,VC++のコンソールで,以下のようにして取得できていたのですが,

// 既にファイルポインタfp1でリードモードでファイルを開いている状態
line01=0;
for(i=0;getc(fp1)!=EOF;i++){
line01=line01+1; // 行数
}

BCC5.5のフリー版でこれをすると,指定したファイルの文字数を返してきます。
1文字で読みとって,EOFが来るまでカウントするので,当然と言えば
当然ですが,VCではうまくいっていました。(VCのバグ?)

データは文字や数字など一定ではないので,fscanfで書式を指定することも
できません。

何かうまい解決策がありましたら教えてください。

<情報>
使用コンパイラ:bcc5.5 フリー版
コンソールモード
使用言語:C(C++でも結構です。)
読み込む対象ファイル:数字,文字,スペースなどで半角・全角を含む文章
したいこと:単純にファイルの行数を取得したい。
です!

ちなみに今書いているソースをつけます。
=================================================================
#include <stdio.h>
#include <process.h> // exit(1);の関数にいる。

void main(void)
{
int i,line01; //カウント用
FILE *fp1;
char filename1[256];

printf(" ファイル名を入力してください。:");
gets(filename1);
fp1=fopen(filename1,"r");
if(fp1==NULL){
printf(" データファイルのオープンに失敗しました。\a\n");
exit(1);
}

line01=0;
for(i=0;getc(fp1)!=EOF;i++){
line01=line01+1;
}

fclose(fp1);

printf("行数 = %d \n",line01);

}
===================================================================
以上です。




No.1309

Re:開いたファイルの行数取得について教えてください。
投稿者---C職人(2002/03/24 13:21:19)


#include <stdio.h>

int main(int argc,char *argv[])
{
FILE *fp;
char line[256];
int lineCnt=0;

/*引数の数チェック*/
if(argc != 2){
fprintf(stderr,"引数の数が不正です。\n");
return 1;
}

/*ファイルオープン*/
fp=fopen(argv[1],"r");
if(fp==NULL){
fprintf(stderr,"ファイル[%s]を開くことができませんでした。\n",argv[1]);
return 1;
}

/*EOFまで一行ずつ読み込み、行数をカウントしていく*/
while(fgets(line,256,fp) != NULL){
lineCnt++;
}

printf("行数は[%d]行です。\n",lineCnt);

return 0;
}

上記のような感じでしょうか
今のままのそちらのソースでは一文字ずつ文字をカウントしていますので
結果的にファイル中の総文字数を返すことになります。
一行ずつ読み込むにはfgetsという関数があるのでどんな関数なのか
自分で調べればわかると思います。


No.1313

Re:開いたファイルの行数取得について教えてください。
投稿者---sato(2002/03/24 23:04:42)


while(fgets(line,256,fp) != NULL){
lineCount++
}
でうまく行きました。
ご指摘のように,一度はfgetsを使っていたのですが,なぜかうまくいかず
悩んでいたんです。

とにかく,おかげさまでうまくいきました。
ありがとうございました。



No.1312

Re:開いたファイルの行数取得について教えてください。
投稿者---B.Smith(2002/03/24 18:53:48)


こんばんは。

ストリーム入出力ならば、関数fgetsで1行単位に読み込むのが最も楽な方法です。
ここでは、メモリ内に全文章を取り込んで、改行文字数をカウントする方法をご紹介します。ファイルサイズがそれほど大きくなければ、メモリに全文取り込んでしまった方が文字列操作処理が楽になり、また全体のパフォーマンスも良くなります。
C++でも良いということなので、今回はC++のソースにしてありますが、通常のCとして見る場合には、メンバ関数LineCountだけ見てください。
//(iostreamは使っていません)
#include <io.h>  
#include <fcntl.h>
#include <mbstring.h>

#include <stdio.h>    //printfのため

class   CFileProcess{  //ファイル操作クラス
    char    *pData;
    int     Size;
public:
    CFileProcess(char *);
    ~CFileProcess(void ){if (pData) delete []pData;};

    int     LineCount(void );    //行数カウント
};

//オブジェクト構築時、ファイルをヒープに読み込んでおく。失敗時、pDataはNULL
CFileProcess::CFileProcess(char *FileName)
{
    pData = NULL;
    int hFile = open(FileName,_O_BINARY | _O_RDONLY);
    if (hFile < 0)  return;

    pData = new char [(Size = filelength(hFile)) + 1];
    if (!pData){close(hFile); return;}

    if (read(hFile,pData,Size) < Size){
        close(hFile); delete []pData; pData = NULL; return;
    };
    *(pData + Size) = 0;
    close(hFile);
};

//行数カウント
//この関数が呼び出される時には、すでにpDataにファイルの全内容を
//読み込んであります(pDataは末尾ヌルの文字列です)
int     CFileProcess::LineCount(void )
{
    //読み込みに失敗している場合は-1を返す
    if (!pData)
        return -1;

    int     LineCnt = 0;     //改行文字数
    char    *pStart = pData; //検索開始位置
    char    *ptr;            //発見した位置

    while(1){
        ptr = _mbsstr(pStart,"\n");//改行文字の検索
        if (!ptr){     //発見できず
            //ポインタが末尾に到達していない場合(文字が残っている場合)は
            //行数をインクリメントする
            if (*pStart) LineCnt++;
            break;
        }

        LineCnt++;           //行数カウント
        pStart = ptr + 1;    //次の検索開始位置
    }

    return LineCnt;
}

void    main(void )
{
    CFileProcess    file("Test.txt");

    printf("%d\n",file.LineCount());
}

これは、対象のファイルをメモリ内に読み込んで、必要な処理を行うことが目的のクラスです。オブジェクトが有効な内は、メンバ変数pDataが指す領域に、読み込んだファイルの内容が末尾ヌルの文字列として残っていますので、対象のファイルに必要な処理を、このクラスに組み込んで拡張することが出来ます。

関数_mbsstrは関数strstrのマルチバイト文字対応版です(mbstring.h)。BCC5.5、Visual C++の両方で使用できます。関数strstrでも良いのですが、全角文字を含む可能性がある場合は、関数_mbsstrを使用した方が安心できます。

単純に改行文字を検索してカウントするだけならば、もうちょっと簡単に出来ますが、その場合、改行文字が存在しない行をカウント出来なくなってしまうので、「改行文字を発見できない場合、文字が残っていたら、それを1行分と見なす」という処理にしています。



No.1314

Re:開いたファイルの行数取得について教えてください。
投稿者---sato(2002/03/24 23:12:39)


ご返答ありがとうございました。
C++で書いてもらって勉強になります。
かなりノーマルCでソースを進めていたため,
while(fgets(buf,1024,fp1)!=NULL){
line01=line01+1;
}
のC職人さんのコードを利用しました。(すみません。)
でも,いずれC++の勉強もしようと思っていましたし,クラスで拡張なども
したいと思いますので,B.Smithさんのソースも勉強させていただきます。
丁寧にご返答頂きありがとうございました。


戻る


「初心者のためのポイント学習C言語」 Last modified:2002.05.26
Copyright(c) 2000-2002 TOMOJI All Rights Reserved