в то время как vs для оператора другое поведение - PullRequest
1 голос
/ 05 августа 2020

Я пытаюсь понять, почему это, в то время как l oop работает так, как ожидалось, но эквивалент (на мой взгляд) для l oop не работает.

#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';
}

l oop -in.txt содержит случайные целые числа: 2 3 4 5 6 1 12 34 3, и результат такой, как ожидалось:

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

Но когда я делаю это для l oop, результат получается странным. См. Ниже.

#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';
}

Результат для l oop:

the vector is:
3
5
1
34

Я пытался понять, чем объявление переменной внутри while l oop отличается от a для l oop, когда я наткнулся на эту проблему. Если я удалю оператор if, вывод for l oop будет правильным. Но я не понимаю, почему он не работает с оператором if, когда while l oop работает нормально. Спасибо всем, что нашли время.

Ответы [ 2 ]

4 голосов
/ 05 августа 2020
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.
}

Есть два чтения в каждой итерации этого l oop, первое в операторе for, второе в теле l oop. Это означает, что вы будете хранить только половину считываемых значений.

Эквивалент while l oop будет выглядеть примерно так (возможно, не точно , но в значительной степени аналогичный эффект):

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, либо прекратите чтение в теле.

1 голос
/ 05 августа 2020

В вместо l oop вы читаете дважды:

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);
}
...