tags:

views:

688

answers:

4

So... when I go:

cout<<stringName<<endl;

I get:

NT

But when I go:

cout<<stringName.c_str()<<endl;

I get:

NTNT

Why?

+1  A: 

This is not a problem with c_str(), but probably related to some other anomaly in the rest of the program.

Make a "hello world" application that does these same operations and you'll see it works fine there.

SoapBox
+2  A: 

Show more code. It seems like you did cout << ealier and forgot that you did it. What does it print if you do cout<< "mofo" << stringName.c_str()<< "|||" << endl; Does it say NTmofoNT||| ? if so that may well be what happened ;)

acidzombie24
+9  A: 

A quick test with the following code:

#include <string>
#include <iostream>

using namespace std;

int main(void) {
    string str = "NT";
    cout << str.c_str() << endl;
    return 0;
}

produces one instance of NT so it looks like you probably have another output call somewhere.

Kevin Loney
How could that be the cause? Assuming he has changed just this one line from 'stringName' to 'stringName.c_str()', that can't change the number of times the string is printed. Plus, he prints a newline, so it's clearly not two instances of this code being run.
Larry Gritz
@Larry There is no indication of what the rest of the code looks like or that the same input was used between runs so it could be in a conditional somewhere. There is also no guarantee that a previous call would include an endl either. I said 'probably' for a reason.
Kevin Loney
@Kevin If there is "another output call" it happens first and doesn't have a newline. I was taking at face value that the only thing he changed was that one line, not the "other". Either way, the CHANGE in behavior as described is not accounted for merely by presence of another "NT" print command.
Larry Gritz
@Larry I agree with you that taking this at face value possible hints at a more difficult to diagnose problem, but my first instinct in a situation like this is to look for the simplest most obvious solution first; especially when given limited details and no context.
Kevin Loney
+5  A: 

A traditional C string (really a char*) has a sequence of characters terminated by a character 0. (Not the numeral '0', but an actual zero value, which we write as '\0'.) There's no explicit length -- so various string operations just read one character at a time until it hits the '\0'.

A C++ std::string has an explicit length in its structure.

Is it possible that the memory layout of your string's characters looks like this:

'NTNT\0'

but the string's length is set to 2?

That would result in exactly this behavior -- manipulating the std::string directly will act like it's just two characters long, but if you do traditional C operations using s.c_str(), it will look like "NTNT".

I'm not sure what shenanigans would get you into this state, but it would certainly match the symptoms.

One way you could get into this state would be to actually write to the string's characters, something like: strcat((char *)s.c_str(), "NT")

Larry Gritz
You would get that behaviour only if std::string::c_str() is faulty. c_str() is guaranteed by the standard (21.3.6[1]) to point to an array (not necessarily the same storage as string uses internally) terminated by a \0
Steve Folly
@Steve, not if c_str() doesn't do anything and the data is already maintained in a null terminated way. Then if you overwrite that null terminator by directly manipulating it with data(), it could have this result.
Greg Rogers
And in general, if you've done anything invalid to the string object and the result is that c_str() doesn't do what you expect, that doesn't mean c_str() is faulty ;-)
Steve Jessop