计算文件中不使用 getline() 的行数

counting lines from file not using getline()

本文关键字:getline 文件 计算      更新时间:2023-10-16

我想从文件中获取一些数据并将其放入变量中。但在此之前,我不知道这个文件的长度。文件如下所示:

 1 12 4
 2 14 5
 3 26 6
 . .. .

这就是为什么我想得到一些行来知道我需要在循环中创建多少变量。在此代码中,我创建了 3 个变量 (a,b,c( 进行尝试。问题是程序结束后的a,b,c只是随机数,而不是1,12和4。我注意到,如果我把这个:

文件>> A>> B>> C;

之前 while 循环它可以工作,但我需要更早的行数。那么如何使用getline()来计算行呢?

int a, b, c;
fstream file;
file.open("abc.txt",ios::in);
if (file.good() == true)
{
    int lines_amount=0;
    string test; 

    while (getline(file,test))
    {
        lines_amount++;
    }
    file >> a >> b >> c;
    file.close();
}

当您使用

while (getline(file,test))
{
      lines_amount++;
}

只有在读取文件中的所有内容后,while循环才会停止。该行

file >> a >> b >> c;

不会读取任何内容abc。这些变量的值是您获得的一些随机值,因为它们以前未初始化过。

将它们初始化为如下所示:

int a = 10, b = 20, c = 30;

你会注意到:

  1. 如果使用 C++11 之前的编译器,则这些变量的值保持不变。
  2. 如果使用 C++11 或更高版本的编译器,则这些变量的值将设置为 0。

为了能够从文件开头读取数字,请将其倒回顶部。您可以使用std::ifstream::seekg。不过,您必须先清除其eofbit

file.clear();
file.seekg(std::ifstream::beg);

倒带文件指示器怎么样?

file.seekg(std::ifstream::beg);

在上一个while循环中,整个文件已经被读取,因此没有任何东西可以进行下一次读取,abc保持不变。在此代码之后,文件指示器将重置为文件的开头,因此您可以再次从头开始读取。

在调用seekg()之前,可能需要添加file.clear()以清除已设置的任何标志,以防止进一步的操作失败。如果设置了错误的标志,他们中的大多数人不会做任何事情。在您的情况下,当尝试读取更多内容时,operator >> ()函数会发现一个错误标志(std::ios_base::iostate::eofbit (并停止。进一步参考

这就是为什么我想得到一些行来知道我需要在循环中创建多少变量。

您不需要事先知道行数。使用std::vector来存储值,并让它在您向其中添加值时动态增长。例如:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
struct values {
    int a, b, c;
};
std::vector<values> data;
std::ifstream file("abc.txt");
if (file.is_open()) {
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        values v;
        if (iss >> v.a >> v.b >> v.c) {
            data.push_back(v);
        }
    }
    file.close();
    // use data as needed...
}

或者:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
struct values {
    int a, b, c;
};
std::istream& operator>>(std::istream &in, values &v) {
    std::string line;
    if (std::getline(in, line)) {
        std::istringstream iss(line);
        if (!(iss >> v.a >> v.b >> v.c)) {
            in.setstate(std::ios_base::failbit);
        }
    }
    return in;
}
std::vector<values> data;
ifstream file("abc.txt");
if (file.is_open()) {
    std::copy(
        std::istream_iterator<values>(file),
        std::istream_iterator<values>(),
        std::back_inserter(data));
    file.close();
    // use data as needed...
}