Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - stringstream << "overwriting"

I'm making an OpenGL game in C++. I'm fairly inexperinced in C++ as opposed to other languages. Anyway, I create a stringstream with the "base" directory for some images. I then pass this stringstream as a function parameter to a constructor. The constructor appends an image file name, then attempts to load the resulting path. However...

D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\ <-- before appending the filename
Ship01.tgacks Projects\SnakeRoid\bin\Debug\Texts\ <-- After.

Obviously not correct! The result should be D:\CodeBlocks Projects\SnakeRoid\bin\Debug\Texts\Ship01.tga

The relevant parts of my code:

std::stringstream concat;
std::string txtFullPath = "Path here";

...

concat.str(""); //Reset value (because it was changed in ...)
concat << texFullPath; //Restore the base path
PS = new PlayerShip(&TexMan, concat); //Call the constructor

The constructor's code

PlayerShip::PlayerShip(TextureManager * TexMan, std::stringstream &path)
{
    texId = 2;
    std::cout << path.str(); //First path above
    path << "Ship01.tga";
    std::cout  << path.str(); //Second - this is the messed up one
    //Do more fun stuff
}

Anyone have any idea why its "overwriting" what's already in the stringstream?

like image 803
Xcelled Avatar asked Dec 17 '22 00:12

Xcelled


1 Answers

why its "overwriting" what's already in the stringstream

Because output places characters at the "put pointer" position in the output buffer. A freshly-constructed stream has the put pointer set to zero (except for file output streams opened in append mode), thus your output overwrites the characters already in the buffer.

If you really need to append strings this way, you need to move the put pointer to the end of the buffer:

std::cout << p.str(); //First path above
std::stringstream path;
path.str(p.str());
path.seekp(0, std::ios_base::end); // <-- add this
path << "Ship01.tga";
std::cout << "Loading player ship from " << path.str(); 

EDIT: The question has been edited and the code after the edit works, because it no longer uses path.str(p.str()); to create the output buffer without using an output operation (and without advancing the put pointer): see ideone for differences.

In any case, strings themselves can be concatenated, which would make the code easier to follow:

std::string p = path.str() + "Ship01.tga";
std::cout << p;

Not to mention that for dealing with files and pathnames, we have boost.filesystem.

like image 118
Cubbi Avatar answered Dec 18 '22 15:12

Cubbi