【问题标题】:while vs for statement different behaviorwhile vs for 语句不同的行为
【发布时间】:2020-08-05 08:29:42
【问题描述】:

我试图理解为什么这个 while 循环按预期工作,但等效的(在我看来)for 循环却没有。

#include <iostream>
#include <fstream>
#include <vector>
using namespace std; 
int main()
{
    ifstream ifs{ "loop-in.txt" };
    if (!ifs)
        perror("can't open input file ");
    vector<int> ys;

    while (true)
    {
        int y;           // get a clean int each time around
        if (!(ifs >> y)) // if it cannot read a int
            break;
        ys.push_back(y); // else: push it into the vector = meaning if(cin>>y)
    }
    cout << "the vector is:\n";
    for (int x : ys)
        cout << x << '\n';
}

loop-in.txt 包含随机整数:2 3 4 5 6 1 12 34 3,输出如预期:

the vector is:
2
3
4
5
6
1
12
34
3

但是当我做这个 for 循环时,输出很奇怪。见下文。

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
    ifstream ifs{ "loop-in.txt" };
    if (!ifs)
        error("can't open input file ");
    vector<int> ys;
    for (int y; ifs >> y;)
    {
        if (!(ifs >> y))
            break;
        ys.push_back(y);
    }
    cout << "the vector is:\n";
    for (int x : ys)
        cout << x << '\n';
}

for循环的输出:

the vector is:
3
5
1
34

当我偶然发现这个问题时,我试图了解在 while 循环中声明变量与 for 循环有何不同。 如果我删除 if 语句,则 for 循环输出是正确的。 但是我不明白为什么当while循环运行良好时它不能与if语句一起使用。 感谢大家抽出宝贵的时间。

【问题讨论】:

  • 获取你最喜欢的rubber duck 并向它解释这个for循环,特别是为什么会有两次读取操作以及y会发生什么;)
  • 您从文件中读取两次ifs &gt;&gt; y(一次在for 循环中,一次在if 条件中)。删除if 条件中的那个。正如 for 循环本身验证的那样,读取是否成功。
  • 旁白:std::vector&lt;int&gt; ys(std::istream_iterator&lt;int&gt;(ifs), {});You don't have to write either loop

标签: c++ for-loop while-loop


【解决方案1】:
for (int y; ifs >> y;)  // <-- Read here.
{
    if (!(ifs >> y))    // <-- And read here, overwriting read above.
        break;
    ys.push_back(y);    // <-- Only pushes every second one.
}

在该循环的每次迭代中都有 两个 读取,第一个在 for 语句中,第二个在循环体中。这意味着您将只存储正在读取的值的一半。

等效的while 循环看起来像这样(可能不是完全,但效果非常相似):

while (true)
{
    int y;           // get a clean int each time around
    if (!(ifs >> y)) // if it cannot read a int
        break;
    if (!(ifs >> y)) // if it cannot read a int
        break;
    ys.push_back(y);
}

要么在for 语句中停止阅读,要么在正文中停止阅读。

【讨论】:

  • 感谢 paxdiablo 的详细回复!真的很有帮助
【解决方案2】:

在for循环中你读了两遍:

for (int y; ifs >> y;) // first read from stream here, then the value of y is not used
{
    if (!(ifs >> y)) // second read here
        break;
    ys.push_back(y);
}

【讨论】:

    猜你喜欢
    • 2015-05-16
    • 2019-02-05
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 2014-09-30
    相关资源
    最近更新 更多