Monday, 11 March 2013

C++ (Sprintf in String) STD Bug (cout)

I have noted a curious difference, perhaps one could say a bug, in the Visual C++ runtime when using std::string with cout...
Now, first of all, what I'm doing it not standard fiar, but lets jump to some code and see what we think it should do...


#include <string>
#include <iostream>

using namespace std;

int main (int p_argc, char* p_argv[])
{
string l_output;
l_output.resize(100);
for (int i = 0; i < 1000; ++i)
{
memset(&l_output[0], 0, l_output.length());
sprintf(&l_output[0], "\r%i\0", i);
cout << l_output;
}

return 0;
}


I expect this code to run in a loop, to output on the same line the numbers 0 through 999, without the newline character being involved, as you can see my sprintf call just returns the carriage, outputs the number and nulls the string for good measure.



But, this is not what happens the call to "cout" results in newlines each call... it seems passing the std::string directly to "cout" causes this, it treats the string as a whole line.






We can stop this with a code change to force the type of char* to be used...


#include <string>
#include <iostream>

using namespace std;

int main (int p_argc, char* p_argv[])
{
string l_output;
l_output.resize(100);
char* l_temp = &l_output[0];
for (int i = 0; i < 1000; ++i)
{
memset(l_temp, 0, l_output.length());
sprintf(l_temp, "\r%i\0", i);
cout << l_temp;
}

return 0;
}


And this works perfectly as expected....






Please note, in the screen shot I had to increase the loop length on the second code example as it competed so quick I could not get a a print screen press before 1000 iterations ended!


I've not gotten to the bottom of this one yet, nor have I checked it out in G++ on linux or on older Visual C++ versions, I had VS2010 in use and spotted this going on... Annoying.

BTW - Yes, this is a good way to use sprintf and string formatting with a std::string.



Update - This does appear to be a bug, it seems the cout::operator<<(std::string) function assumes a return carriage, new line (\r\n) at the end, treating this as a "WriteLine", rather than an out string, and so you have to cout << stringValue.c_str(); to avoid this problem.

No comments:

Post a Comment