【问题标题】:C++17 if init for the while loop?C ++ 17 if init for while循环?
【发布时间】:2017-05-27 20:34:13
【问题描述】:

对于一些家庭作业,我正在做以下工作:

int main() {

    ofstream file("log.txt");

    file << setw(5)  <<  "i"
         << setw(15) <<  "h"
         << setw(15) <<  "n"
         << setw(15) <<  "sum"
         << setw(15) <<  "diff"
         << endl;

    auto write2file = [&file](int i, double h, double n, double sum, double diff) {
        file << setw(5)  << i
             << setw(15) << h
             << setw(15) << n
             << setw(15) << sum
             << setw(15) << diff
             << endl;
    };

    double a = 0;
    double b = 2;
    int n = 1;
    double h = (b-a)/n;
    double sum = sum_analytic;
    double diff = 1;

    while (diff > pow(10, -4)) {
        h = (b-a)/++n;
        sum = ntgrt(a, b, n, h);
        diff = abs(sum - sum_analytic);

        static int i = 0;
        write2file(++i, h, n, sum, diff);
    }
}

考虑到 C++17 if init 功能 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html) 当我在 while 循环之外声明 hsumdiff 时,我在这里看到了相同的模式,但它们仅在内部使用。

有没有更好的写法,可能是利用 C++17 的特性?

【问题讨论】:

  • 只是好奇:n 似乎是一个简单的迭代变量,但您没有提到它仅在循环内部使用。你在其他地方也需要吗?如果没有,您可以查看this 问题的答案。 (假设您选择 Nicol Bolas 的方式,并且只使用 for 循环而不是 while 循环。)

标签: c++ c++14 c++17


【解决方案1】:

那么你想要的是一个for 循环:

for(double diff = 1; diff > pow(10, -4);)
{
    double h = (b-a)/++n;
    double sum = ntgrt(a, b, n, h);
    diff = abs(sum - sum_analytic);
    ....
}

将此功能添加到while 没有任何意义,因为您可以只使用for 并省略增量语句。

【讨论】:

  • 我认为这是一个很好的答案。将变量保持在循环范围内的好方法,就像 C++ Core Guidelines 的建议一样。谢谢。
  • #define whileinit(init, test) for(init; (test);)(不是说你应该这样做)
  • @AyxanHaqverdili 证明有充分的理由添加该功能。
  • “没有意义”——我的意思是,重点是 for 循环需要重复更新表达式,while 不会。考虑for (auto e = readdir(dir); e; e = readdir(dir)) …
  • @KonradRudolph:e = readdir(dir) 不会导致对e 的引用吗?哪些可以测试?所以这相当于for(auto e = readdir(dir); e = readdir(dir);)。假设的while 版本有何不同?毕竟,它不能不断地重新创建 e 变量。
【解决方案2】:

我会从一些 C++98 特性开始以减少重复。

template <class I, class F>
void write2file(std::ostream &os, I i, F h, I n, F sum, F diff) {
    using std::setw;

    os  << setw(5) << i
        << setw(15) << h
        << setw(15) << n
        << setw(15) << sum
        << setw(15) << diff
        << "\n";
}

// ...
write2file(file, "i", "h", "n", "sum", "diff");


// ...
write2file(file, ++i, h, n, sum, diff);

在使用它们时,in 似乎总是具有相同的值。我只使用两者之一而不是两者。

你的pow(10, -4) 可能会更好1e-4

我认为对 C++98 的一些好的使用可能也可以清理循环。我会把它移到一个函数模板中,按照这个一般顺序:

template <typename F>
void show_convergence(double a, double b, F f, double sum_a, std::ostream &os) {
    double diff = 1.0;

    for (int n=1; diff > 1e-4; n++) {
        double h = (b-a)/n;
        double sum = f(a, b, n, h);
        diff = abs(sum-sum_a);
        write2file(os, n, h, sum, diff);
    }
}

从技术上讲,这必须是一个模板——但它相当无害,并且避免了指向函数的指针的丑陋(这也可能导致相当程度的低效率) .然后你会这样称呼它:

show_convergence(0, 2, ntgrt, sum_analytic, file);

【讨论】:

  • 作为模板的替代品,做auto write2file = [&amp;](auto n, auto h, auto sum, auto diff){...会不会很有趣?
  • 你可以,但我认为它足够大(而且它的大部分内容与其他任何东西都足够无关),在我看来,将它单独移出更有意义。
  • @Shadow:哎呀。已更正。
猜你喜欢
  • 2021-10-31
  • 1970-01-01
  • 2013-06-22
  • 2021-11-23
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多