开发者

ifstream fails without any reason?

开发者 https://www.devze.com 2023-03-08 19:28 出处:网络
I have a list of 3d spheres, when I save the list, I loop through: void Facade::Save(std::ostream& fs)

I have a list of 3d spheres, when I save the list, I loop through:

void Facade::Save(std::ostream& fs)
{
    fs<<x<<" "<<y<<" "<<z<<" "<<r<<" "; //save fields
    fs<<color[0]<<" "<<color[1]<<" "<<color[2]<<std::endl;
}

and when I restore the list, I use:

    void Facade::Load(std::ifstream& fs, BallList* blist)
    {
        GLfloat c[3];
        fs>>x>>y>>z>>r;
        //fails there, why
        fs>>c[0]>>c[1]>>c[2];
        .....   
    }

I don't know what goes wrong, but when reading the last line, the color components of the last sphere cannot be read, the stream fails after reading the radius of the last sphere. I checked the sphere list file:

7.05008 8.99167 -7.16849 2.31024 1 0 0
3.85784 -3.93902 -1.46886 0.640751 1 0 0
9.33226 3.66375 -6.93533 2.25451 1 0 0
6.43361 1.64098 -6.17298 0.855785 1 0 0
6.34388 -0.494705 -6.88894 1.50784 1 0 0 

This looks good. Can somebody tell me why is this happening? Is this a bug of ifstream? I'm using Unicode by the way.


The loops are attached below:

void BallList::Load(std::istream& fs)
{
    Clear();
    Facade ball1;
    while(!fs.fail() && !fs.eof())
    {
        ball1.Load(fs, this);
        Add(ball1);
    }
    /*
    balls.pop_back(); //this is a work around, get rid of the last one
    originalballs.pop_back();
    */
}

void BallList::Save(std::ostream& fs)
{
    vector<Facade>::iterator itero = this->originalballs.begin();
    while (itero != this->开发者_运维技巧originalballs.end())
    {
        itero->Save(fs);
        itero++;
    }

    /*
    //work around the ifstream problem: the color of the last sphere cannot be read
    //add a dummy item as the last
    itero = this->originalballs.begin();
    if(itero != this->originalballs.end())
    {
        itero->Save(fs);
    }
    */
}


I would expect this to fail after reading 5 balls (spheres) correctly.

The loop is designed so that attempting to read the 6th ball will fail but Add() is still called!! You should redefine your code a bit:

std::ifstream& Facade::Load(std::ifstream& fs, BallList* blist)
{
    GLfloat c[3];
    fs>>x>>y>>z>>r;        // This will fail if there is no input.
                           // Once all 5 balls have been read
                           // There is only a new line character on the stream.
                           // Thus the above line will fail and the fail bit is now set.
    fs>>c[0]>>c[1]>>c[2];

    return fs;  // returned so it can be tested in loop.
}

void BallList::Load(std::istream& fs)
{
    Clear();
    Facade ball1;
    while(ball1.Load(fs, this))  // Only enter loop if the load worked
    {                            // Load worked if the stream is in a good state.
        // Only call Add() if Load() worked.
        Add(ball1);
    }
}

PS. White space is your friend. Personally I think this is easier to read:

    fs >> x >> y >> z >> r;
0

精彩评论

暂无评论...
验证码 换一张
取 消