如何在C++中计算文件的行数?

43

如何使用标准类 fstreamifstream 计算行数?


12
闻起来像是作业题目 - 你已经尝试了什么? - KevinDTimm
13
从数字'1'开始,每行依次加1。 - Edward Strange
6
@Noah:空文件有一行吗? - Martin York
2
@Martin - 你是对的。失败了。 - Edward Strange
2
这一定是重复的,因为我写了一篇博客文章,基于另一个人在Stack Overflow上问这个问题的时间。http://www.adrianmccarthy.com/blog/?p=37 - Adrian McCarthy
1
“line”的定义是什么 - 最后一个换行符和文件结尾之间的内容是否计入其中?如果有一个换行符直接跟在EOF后面会怎样? - Greg Domjan
8个回答

127

怎么样,试试这个:

  std::ifstream inFile("file"); 
  std::count(std::istreambuf_iterator<char>(inFile), 
             std::istreambuf_iterator<char>(), '\n');

8
@fingerprint211b:在结果中加上一个数字 :-) 在文件末尾是否要加上换行符总是存在这种权衡。 - Abhay
6
优美而典雅,喜欢那个STL。 - wheaties
3
@MIH:通过快速的谷歌搜索,你会发现std::count()<algorithm> 头文件中。 - James McNellis
4
@MIH1406:#include <algorithm> - Abhay
3
重点是size_t n = 0; while (getline (stream, string)) n++;将准确报告行数,无论文件是否具有POSIX eof。如此回答中所示的std::count方法将无法计算最后一行--即使存在要读取的文本。行数应该是准确的。整个问题的底层原因是为什么少数文本编辑器继续使用非POSIX结尾来写文件。:) - David C. Rankin
显示剩余14条评论

13

这是正确版本的Craig W. Wright的回答:

int numLines = 0;
ifstream in("file.txt");
std::string unused;
while ( std::getline(in, unused) )
   ++numLines;

std::getline(in, std::string()) - 将非常数引用绑定到临时对象在C++中是不合法的。 - Pietro

13

你逐行读取文件。 计算你读取的行数。


32
听起来好像是一个非常过分复杂的事情!;-) - James McNellis
哪个是正确的。使用缓冲区读取是捕获非POSIX eof 的唯一方法。 - David C. Rankin

3

遵循@Abhay的核方法

我完成了一个完整的代码:

#include <fstream>

std::size_t count_line(std::istream &is) {
    // skip when is not open or got bad
    if (!is || is.bad()) { return 0; }
    // save state
    auto state_backup = is.rdstate();
    // clear state
    is.clear();
    auto pos_backup = is.tellg();

    is.seekg(0);
    size_t line_cnt;
    size_t lf_cnt = std::count(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), '\n');
    line_cnt = lf_cnt;
    // if the file is not end with '\n' , then line_cnt should plus 1
    // but we should check whether file empty firstly! or it will raise bug
    if (is.tellg() != 0) {
        is.unget();
        if (is.get() != '\n') { ++line_cnt; }
    }

    // recover state
    is.clear() ; // previous reading may set eofbit
    is.seekg(pos_backup);
    is.setstate(state_backup);

    return line_cnt;
}

它不会改变原始文件流的状态,包括处理最后一行缺失'\n'的情况。

感谢@masoomyf指出我的错误,我太蠢了没想到!


1
如果文件为空或不存在,则返回1。 - masoomyf
我认为0可能更好? - fishshrimp鱼虾爆栈
如果文件不存在或者文件为空,则此函数返回0。但是对于空白文件,该函数也会返回零。 - masoomyf
如果“空白文件”是一个只包含空格的文件,则该函数可以按预期返回1~ - fishshrimp鱼虾爆栈
@masoomyf 你好,经过将近5年的时间,我终于明白了你的观点。太愚蠢了,不仅是我的英语,还有我的逻辑。谢谢。 - fishshrimp鱼虾爆栈

0
这对我有效:
  std::ifstream fin{"source.txt"};
  std::count(std::istream_iterator<char>(fin >> std::noskipws), {}, '\n');

0
int aNumOfLines = 0;
ifstream aInputFile(iFileName); 

string aLineStr;
while (getline(aInputFile, aLineStr))
{
    if (!aLineStr.empty())
        aNumOfLines++;
}

return aNumOfLines;

一条空白行仍然是一行,因此应该移除 empty() 检查。 - Remy Lebeau
@RemyLebeau 这取决于你如何定义行,而这个问题的提问者并没有明确说明。 - Rick

-3

int numLines = 0;
ifstream in("file.txt");
//while ( ! in.eof() )
while ( in.good() )
{
   std::string line;
   std::getline(in, line);
   ++numLines;
}

关于文件的最后一行如果没有以换行符结尾应该如何处理,这是一个问题。根据你的需求,你可能想要计算它,也可能不想计算。这段代码会计算它。

参见:http://www.cplusplus.com/reference/string/getline/


7
不要使用while ( ! in.eof() )这样的语句,如果在读取文件时出现任何故障,它会产生垃圾数据。应该将std::getline作为while循环的条件。 - Billy ONeal
3
由于您在编辑后,如果 std::getline 失败,会增加行数计数器,并且直到之后才检查是否成功,因此仍然无效。将 std::getline 移到 while 循环的条件中。请注意不要改变原意。 - Billy ONeal

-15

将文件大小除以每行平均字符数!


2
如何在不读取文件的情况下确定每行平均字符数?如果您正在计算字符,那么最好只计算换行符;这有点否定了您的答案。 - Thomas Matthews
3
太棒了!这正是我从前任手中得到的99.99%代码的写法! - Herwig
1
你的解决方案值得诺贝尔奖。 - Orif Milod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接