I don't know if I am overlooking or misunderstanding something, but I am seeing some strange behavior.
I am writing a text based game and have a Player class that is a base for a ConsolePlayer, NetworkPlayer and AIPlayer. I have included a public stringstream object called print so any function can pass data to the player via the familiar insertion operators, i.e.
Code:
player.print << "There were " << totalhearts << " hearts." << endl;
If anyone knows of a better way to handle this, I'm all ears!
My design is that the player objects will all be updated every pulse, and a printStream() function will be called during these updates to extract the output from the stringstream and deliver it to the appropriate mechanism (cout for ConsolePlayer, a send() or queue() function for NetworkPlayer, and push_back() onto a vector for AIPlayer so it can sort through the lines as needed). The extraction process will be the same regardless of the type, and a string will be sent to a function that the child class must overload.
Also, like cout, I only want to send full lines (ending with a newline '\n') except in special circumstances which are outside the scope of this function.
Here is my code:
Code:
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
void printStream(stringstream &print);
int main()
{
// create a string stream
stringstream teststream;
teststream << "01 one 789" << endl
<< "01 two 789" << endl
<< "0 three 89" << endl
<< "01 four 89" << endl;
// try and print it with the function already written
printStream(teststream);
return 0;
}
void printStream(stringstream &print)
{
// if the print stream is empty, we're done
if ( print.str().empty() )
return;
string working(print.str());
unsigned int begin = 0;
unsigned int end = 0;
unsigned int size = working.size();
while ( (end = working.find('\n', begin)) != std::string::npos )
{
++end; // move to one past the \n, substr will then print the \n
// and ignore the char one-past it and begin needs to move
// to one-past the \n so we don't match the same \n again
std::cout << "{b" << setw(3) << begin
<< ",e" << setw(3) << end
<< ",s" << setw(3) << size << "} "
<< working.substr(begin, end);
begin = end;
}
cout << "Begin: " << begin << endl
<< "End: " << end << endl
<< "Size: " << size << endl;
if (begin == 0) // didn't find a '\n', so didn't print anything
{
cout << "No \\n's found." << endl;
return;
}
print.clear(); // clear the stream
if (begin != size) // if we didn't print the whole thing
print.str(working.substr(begin)); //assign the remainder to the stream
cout << endl << "string stream ends up as follows:" << endl
<< ">" << print.str() << "<" << endl;
return;
}
This function is copied exactly from the program, including debug output (like printing the begin, end and size before each line), except that in the class the stringstream is not passed to the function because both are part of the class. This function does the exact same thing in this test program as it does when I compile the skeleton of the game I have so far, so I don't believe the problem is in anything other than this function. I also stripped all the std::'s from the std items and included the using namespace std; just so I could focus on the logic in this simple test program and not have to wade through all the std::'s.
The cout in the while loop is there only for testing, it will be replaced with a call to the function that must be overloaded by the child classes and will take a single string representing the line of output that was extracted.
I am compiling and running this via g++ version 3.4.4 under cygwin (WinXP). Here is the output I get:
Code:
Asha$ sstest
{b 0,e 11,s 44} 01 one 789
{b 11,e 22,s 44} 01 two 789
0 three 89
{b 22,e 33,s 44} 0 three 89
01 four 89
{b 33,e 44,s 44} 01 four 89
Begin: 44
End: 4294967295
Size: 44
string stream ends up as follows:
>01 one 789
01 two 789
0 three 89
01 four 89
<
Asha$
As you can see, even though begin and end are pointing to the appropriate places in the string, working.substr(begin, end) is returning far more than it should. Line one is printed just fine, but then lines two and three are printed, and then lines three and four, and so on. I don't understand why this is happening.
As an added bonus, print.clear(); apparently fails to do anything at all. I am using it exactly as cppreference.com shows. I replaced it with print.str(""); which works but seems like a kludge to me (though I guess the stringstream probably does the same thing as .clear() before assigning the empty string).
I can't see any reason why this isn't working right. What am I missing?