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;
精彩评论