counting the number of lines in a text file

I'm reading lines off of text file and I'm wondering if this is a good way to go? I had to write the function numberoflines to decrease the number_of_lines variable by one because within the while loop, for every line it read it adds 2 to the number_of_lines variable.

#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;
}

Is there any other easier better way?

24
задан BЈовић 16 May 2013 в 09:20
поделиться

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;
}
55
ответ дан 28 November 2019 в 22:44
поделиться

Думаю, ваш вопрос: «Почему я получаю на одну строку больше, чем в файле?»

Представьте себе файл:

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 , чтобы указать конец файла, верно? Неа! Это потому, что getline устанавливает eof , если маркер конца файла достигнут «во время его работы» . Поскольку 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 (неявное преобразование в тип bool):

while(getline(myfile,line)){
    cout<< ...
6
ответ дан 28 November 2019 в 22:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: