从文件中逐行读取条件

conditional line-by-line reading from file

本文关键字:读取 条件 逐行 文件      更新时间:2023-10-16

现在我有那个代码:

if (minimizator_weighted) {
    while (dataFile >> t >> e >> sigma) { // read data file value by value
        /* some code */
    }
}
else {
    while (dataFile >> t >> e) { // all the same but will not read standard deviation
        /* almost the same code */
    }
}

您可以看到ifelse流量之间的唯一区别是while循环的条件。我想知道是否有可能优化该片段并重新使用代码?如果我能写出某种:

,那就太好了
while ((minimizator_weighted) ? (dataFile >> t >> e >> sigma) : (dataFile >> t >> e)) { ... }

但是我不确定这个技巧是否正确...您能告诉我一些优化吗?谢谢!

编辑这是完整的代码片段

if (minimizator_weighted) {
    while (dataFile >> t >> e >> sigma) { // read data file value by value
        data_set::pt point;
        point.t = t;
        point.e = e;
        point.c_vis = 0.0;
        point.c_invis = 0.0;
        if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
            sigma = 1.0;
        point.sigma = sigma;
        set.curve.push_back(point); // store point
        data_numPoints++; // collect some stats
        set.curveAvg += e;
    }   
}   
else {
    while (dataFile >> t >> e) { // all the same but will not read standard deviation
        data_set::pt point;
        point.t = t;
        point.e = e;
        point.c_vis = 0.0;
        point.c_invis = 0.0;
        set.curve.push_back(point);
        data_numPoints++;
        set.curveAvg += e;
    }   
}

添加一个间接水平

bool read_data_line1(istream& dataFile, T& t, E& e, Sig& sigma)
{ return dataFile >> t >> e >> sigma; }
bool read_data_line2(istream& dataFile, T& t, E& e, Sig&)
{ return dataFile >> t >> e; }
auto read_data_line_func = minimizator_weighted ? read_data_line1 : read_data_line2;
while(read_data_line_func(dataFile, t, e, sigma))
{
    data_set::pt point;
    point.t = t;
    point.e = e;
    point.c_vis = 0.0;
    point.c_invis = 0.0;
    if (minimizator_weighted)
    {
      if (std::abs(sigma) <= GSL_SQRT_DBL_MIN) // check for division-by-zero error
        sigma = 1.0;
      point.sigma = sigma;
    }
    set.curve.push_back(point); // store point
    data_numPoints++; // collect some stats
    set.curveAvg += e;
}

我想我会表达这样的东西:

data_set::pt collect_point(std::istream& is, bool minimizator_weighted)
{
    data_set::pt point;
    is >> point.t >> point.e;
    point.c_vis = 0.0;
    point.c_invis = 0.0;
    if (minimizator_weighted) {
        is >> point.sigma;
        point.sigma = std::max(point.sigma, GSL_SQRT_DBL_MIN);
    }
    return point;
}
void test()
{
  int data_numPoints = 0;
  data_set set;
  while (dataFile)
  {
    auto point = collect_point(dataFile, minimizator_weighted);
    auto e = point.e;
    set.curve.push_back(std::move(point)); // store point
    data_numPoints++; // collect some stats
    set.curveAvg += e;
  }
}

您的体系结构向我们展示了3件错误:

  1. sigma是某些对象的未使用变量
  2. 对象行为由外部变量(minimizator_weighted
  3. 决定
  4. minimizator_weighted必须每次访问这些对象之一

这些是基本的设计缺陷,不仅使您在这里付出了代价,而且在整个程序中损失了。该修复程序将需要进行reachiptuction。让我向您展示如何做到这一点,您可以决定是否要继续解决问题或解决架构。

首先您需要 2 基本类型,1 st 将与您已经定义的没有sigmadata_set::pt匹配,然后我们将使用data_set::pt_weighted扩展添加sigma

struct pt {
    double t;
    double e;
    double c_vis;
    double c_invis;
};
struct pt_weighted : pt {
    double sigma;
};

现在我们要编写提取操作员,再次以data_set::pt的提取操作符开始,并将其扩展为data_set::pt_weighted

istream& operator>> (istream& lhs, data_set::pt& rhs) {
    rhs.c_vis = 0.0;
    rhs.c_invis = 0.0;
    return lhs >> rhs.t >> rhs.e;
}
istream& operator>> (istream& lhs, data_set::pt_weighted& rhs) {
    lhs >> static_cast<data_set::pt&>(rhs) >> rhs.sigma;
    // check for division-by-zero error
    if(std::abs(rhs.sigma) <= GSL_SQRT_DBL_MIN) rhs.sigma = 1.0;
    return lhs;
}

从这里开始,您需要开始使用模板。首先,您需要将set.curve示为data_set::ptdata_set::pt_weighted的容器,然后您的功能需要更改为:

template <typename T>
void foo() {
    for(T point; dataFile >> point;) {
        set.curve.push_back(point); // store point
        data_numPoints++; // collect some stats
        set.curveAvg += point.e;            
    }
}

如果您无法在运行时建立minimizator_weighted,则需要致电foo,例如:

minimizator_weighted ? foo<data_set::pt_weighted>() : foo<data_set::pt>();