Подсчет количества строк в текстовом файле
Я читаю строки из текстового файла, и мне интересно, если это хороший способ пойти? Мне пришлось написать функцию numberoflines
, чтобы уменьшить значение number_of_lines variable
на единицу, потому что внутри цикла while для каждой прочитанной строки она добавляет 2 к переменной number_of_lines.
#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;
}
Есть ли другой более простой способ?
Ответы
Ответ 1
Ваш взломать счетчик в конце - это именно то, что - взломать.
Намного лучше написать ваш цикл правильно, так что он не будет считать последнюю строку дважды.
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;
}
Изменить: Конечно, С++ также позволит вам сделать что-то похожее:
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;
}
Ответ 2
Я думаю, ваш вопрос: "Почему я получаю еще одну строку, чем в файле?"
Представьте файл:
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<< ...
Ответ 3
В C, если вы реализуете линию подсчета, она никогда не завершится.
Да, вы можете получить одну дополнительную строку, если в конце файла находится "ВВОД КЛЮЧ" .
Файл может выглядеть примерно так:
"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;
}