C++中计算文件行数的最简洁方法

3

如何最简洁地计算文件的行数?我需要这个信息来创建/初始化一个矩阵数据结构。

稍后我需要再次遍历文件并将信息存储在矩阵中。

更新:根据Dave Gamble的建议,但为什么它不能编译?请注意,文件可能非常大。因此,我尝试避免使用容器以节省内存。

#include <iostream>      
#include <vector>        
#include <fstream>       
#include <sstream>       
using namespace std;     


int main  ( int arg_count, char *arg_vec[] ) {
    if (arg_count !=2 ) {
        cerr << "expected one argument" << endl;
        return EXIT_FAILURE;      
    }

    string line;
    ifstream myfile (arg_vec[1]);

    FILE *f=fopen(myfile,"rb");
    int c=0,b;
    while ((b=fgetc(f))!=EOF) c+=(b==10)?1:0;
    fseek(f,0,SEEK_SET);


    return 0;
}

1
猜测是你需要 #include <stdio.h> - GManNickG
2
FILE *f=fopen(arg_vec[1],"rb"); 请。 - Dave Gamble
1
fopen 接受一个文件名,而不是 ifstream。 - Dave Gamble
1
此外,如果您没有使用fopen/fgetc或其他类似函数,请将fseek(...)替换为fclose(f);。 - Dave Gamble
1
作为良好的实践,我建议在fclose(f)之后再创建ifstream,否则你会打开同一个文件两次。 - Dave Gamble
显示剩余2条评论
5个回答

10

如果你需要“返回”是因为没有大小无法继续,尝试重新排列你的设置。

也就是说,读取文件,将每行存储在std::vector<string>或其他类似的数据结构中。这样你就有了文件的大小以及每一行的内容:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

int main(void)
{
    std::fstream file("main.cpp");
    std::vector<std::string> fileData;

    // read in each line
    std::string dummy;
    while (getline(file, dummy))
    {
        fileData.push_back(dummy);
    }

    // and size is available, along with the file
    // being in memory (faster than hard drive)
    size_t fileLines = fileData.size();

    std::cout << "Number of lines: " << fileLines << std::endl;
}

以下是没有使用容器的解决方案:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

int main(void)
{
    std::fstream file("main.cpp");
    size_t fileLines = 0;    

    // read in each line
    std::string dummy;
    while (getline(file, dummy))
    {
        ++fileLines;
    }

    std::cout << "Number of lines: " << fileLines << std::endl;
}

尽管我怀疑这不是最有效的方法。这种方法的好处在于能够逐行存储内存。


这是我要建议的方法,但我已经很久没有使用C++了,所以在发布之前我必须测试它。谢谢你节省了我的时间+1 :D - Sam Harwell
3
我非常喜欢当我能够通过源文件名作为输入来判断某人是否真正测试过代码 :D:D - Dave Gamble
哈哈,是啊。当我想到“我需要一个文件来测试……哦,傻瓜”时,我有了那个“bingo!”的时刻。 - GManNickG
如果我们只需要计数,std::istream::ignore() 应该比 getline 更有效率。 - Luc Hermitte

10

我认为这可能就是答案...

std::ifstream file(f);
int n = std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n') + 1;

6
FILE *f=fopen(filename,"rb");

int c=0,b;while ((b=fgetc(f))!=EOF) c+=(b==10)?1:0;fseek(f,0,SEEK_SET);

在 C 语言中回答。是指紧凑型的吗?


呃。【啦啦啦15个字符】 - GManNickG
2
感谢我留下了?1:0。没有它也能正常工作。我本可以在那里节省4个字符 ;) - Dave Gamble
4
int c=0;while(!fscanf(f,"%*[^\n]%*c"))c++;fseek(f,0,SEEK_SET) - Adam Rosenfield
我从未知道scanf可以接受正则表达式参数...仍然是一个非常酷的技巧! - Dave Gamble
@Dave:你的解决方案能处理空行吗?另外,fseek的目的是什么?我运行了你的代码,没有使用它,它打印了正确的行号。 - Hristo
显示剩余3条评论

3
#include <stdlib.h>
int main(void) { system("wc -l plainfile.txt"); }

1

计算 '\n' 的出现次数。 它适用于*nix(\n)和DOS/Windows(\r\n)的行尾,但对于旧式Mac(System 9或之前)则不适用,它只使用\r。 我从未见过仅使用\r作为行尾的情况,所以除非你知道这将是一个问题,否则我不会担心它。

编辑:如果您的输入不是ASCII,则还可能遇到编码问题。 您的输入长什么样?


可能不是跨平台的(我只是这么说)。 - Kredns

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