web-dev-qa-db-ja.com

テキストファイルの行数を数える

私はテキストファイルの行を読んでいますが、これが良い方法かどうか疑問に思っていますか? _number_of_lines variable_を1減らす関数numberoflinesを書く必要がありました。なぜなら、whileループ内では、読み込む行ごとにnumber_of_lines変数に2を追加するからです。

_#include <iostream>
#include <fstream>
using namespace std;

int number_of_lines = 0;

void numberoflines();
int main(){
    string line;
    ifstream myfile("textexample.txt");

    if(myfile.is_open()){
        while(!myfile.eof()){
            getline(myfile,line);
            cout<< line << endl;
            number_of_lines++;
        }
        myfile.close();
    }
    numberoflines();

}

void numberoflines(){
    number_of_lines--;
    cout<<"number of lines in text file: " << number_of_lines << endl;
}
_

他のもっと簡単なもっと良い方法はありますか?

23
silent

最後にカウントを減らすというあなたのハックはまさに​​それです-ハックです。

そもそもループを正しく記述する方がはるかに良いので、最後の行を2回カウントしません。

int main() { 
    int number_of_lines = 0;
    std::string line;
    std::ifstream myfile("textexample.txt");

    while (std::getline(myfile, line))
        ++number_of_lines;
    std::cout << "Number of lines in text file: " << number_of_lines;
    return 0;
}

個人的には、この場合、Cスタイルのコードは完全に受け入れられると思います。

int main() {
    unsigned int number_of_lines = 0;
    FILE *infile = fopen("textexample.txt", "r");
    int ch;

    while (EOF != (ch=getc(infile)))
        if ('\n' == ch)
            ++number_of_lines;
    printf("%u\n", number_of_lines);
    return 0;
}

編集:もちろん、C++でも少し似たようなことができます。

int main() {
    std::ifstream myfile("textexample.txt");

    // new lines will be skipped unless we stop it from happening:    
    myfile.unsetf(std::ios_base::skipws);

    // count the newlines with an algorithm specialized for counting:
    unsigned line_count = std::count(
        std::istream_iterator<char>(myfile),
        std::istream_iterator<char>(), 
        '\n');

    std::cout << "Lines: " << line_count << "\n";
    return 0;
}
54
Jerry Coffin

あなたの質問は、「ファイルにある行よりも1行多くなっているのはなぜですか?」

ファイルを想像してください:

_line 1
line 2
line 3
_

ファイルはASCIIのように表されます:

_line 1\nline 2\nline 3\n
_

(ここで_\n_はバイト_0x10_です。)

それでは、各getline呼び出しの前後に何が起こるか見てみましょう:

_Before 1: line 1\nline 2\nline 3\n
  Stream: ^
After 1:  line 1\nline 2\nline 3\n
  Stream:         ^

Before 2: line 1\nline 2\nline 3\n
  Stream:         ^
After 2:  line 1\nline 2\nline 3\n
  Stream:                 ^

Before 2: line 1\nline 2\nline 3\n
  Stream:                 ^
After 2:  line 1\nline 2\nline 3\n
  Stream:                         ^
_

さて、あなたはストリームがファイルの終わりを示すためにeofをマークすると思いますよね?いや!これは、ファイルの終わりマーカーに到達するとgetlineeofを設定するためです "操作中"getlineは_\n_に達すると終了するため、ファイルの終わりマーカーは読み取られず、eofにはフラグが付けられません。したがって、myfile.eof()はfalseを返し、ループは別の繰り返しを通過します。

_Before 3: line 1\nline 2\nline 3\n
  Stream:                         ^
After 3:  line 1\nline 2\nline 3\n
  Stream:                         ^ EOF
_

これをどのように修正しますか? eof()を確認する代わりに、.peek()EOFを返すかどうかを確認します。

_while(myfile.peek() != EOF){
    getline ...
_

getlineの戻り値をチェックすることもできます(暗黙的にブールにキャストします):

_while(getline(myfile,line)){
    cout<< ...
_
6
strager

Cでcount行を実装すると、失敗することはありません。はい。通常、ファイルの最後に迷い"ENTER KEY"がある場合、1行余分に取得できます。

ファイルは次のようになります。

"hello 1
"Hello 2

"

以下のコード

#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "file1.txt"

int main() {

    FILE *fd = NULL;
    int cnt, ch;

    fd = fopen(FILE_NAME,"r");
    if (fd == NULL) {
            perror(FILE_NAME);
            exit(-1);
    }

    while(EOF != (ch = fgetc(fd))) {
    /*
     * int fgetc(FILE *) returns unsigned char cast to int
     * Because it has to return EOF or error also.
     */
            if (ch == '\n')
                    ++cnt;
    }

    printf("cnt line in %s is %d\n", FILE_NAME, cnt);

    fclose(fd);
    return 0;
}
0
ashish

forループあり:

std::ifstream myFile;
std::string line;
int lines;

myFile.open(path);

for(lines = 0; std::getline(myFile,line); lines++);

std::cout << lines << std::endl;
0
Altinsystems