2

When running this code I get "Hello Worldaaa", but according to the job of the .c_str() function, the string a should be "Hello World\0" and string b should be "Hello World\0aaa" so "aaa" should not show up in the output.

#include <bits/stdc++.h>

using namespace std; 

int main()
{
    string a = "Hello World";
    a = a.c_str();
    string b = a + string("aaa");

    cout << b;

    return 0;
}
  • 3
    _["Returns a pointer to a null-terminated character array with data equivalent to those stored in the string."](https://en.cppreference.com/w/cpp/string/basic_string/c_str)_ It does, but using it in the `std::string operator+(const char*, const std::string&)` ignores the terminating `'\0'` character to produce the result. – πάντα ῥεῖ Mar 06 '19 at 17:46
  • 2
    it's not actually `.c_str()`, it's actually the constructor that's confusing you. – Mooing Duck Mar 06 '19 at 17:47
  • Possible duplicate of [How do you construct a std::string with an embedded null?](https://stackoverflow.com/questions/164168/how-do-you-construct-a-stdstring-with-an-embedded-null) – πάντα ῥεῖ Mar 06 '19 at 18:00

3 Answers3

4

Yes, you are right regarding std::string::c_str.

Indeed,

Returns a pointer to a null-terminated character array with data equivalent to those stored in the string.

However, there are a few considerations which probably misleading you.


First of all, the statement:

a = a.c_str();

is semantically a no-operation. You get the const char* (i.e. "Hello World\0") and assign it to a. However a is a std::string, it is a class designed to abstract a "string type" in C++. It handles automatically the '\0', transparently. The user is not supposed to care about the managing of it1.

The trick is inside std::string::operator=(const char*).

Replaces the contents with those of null-terminated character string pointed to by s as if by assign(s, Traits::length(s)).


The last point, about string concatenation.

a + string("aaa");

As previously, in this case, the operator std::string::operator+ will handle the '\0'.

Shortly, it behaves like:

"Hello World\0" + "aaa\0"  ===> "Hello Worldaaa\0"

It will care about the "inner '\0'" returning a conforming null-terminated string.


1 Unless he/she is playing with the internal memory.

BiagioF
  • 9,368
  • 2
  • 26
  • 50
  • Really, the point needs to be made that in a "NUL-terminated string", the NUL terminator is not considered part of the *string's data*. It is merely an end-of-string indicator. That is, `"Hello World"` is a different string from `"Hello World\0"`; the latter has an embedded NUL character which is part of the actual string. – Nicol Bolas Mar 06 '19 at 18:24
0

That would be unintuitive. Remember that the terminating null character wasn't explicitly used by the user. Syntax of the language added it.

It will create a lot of confusion if the result of "abcd" + "xyz" ends up being "abcd\0xyz" instead of the intuitive result - "abcdxyz".

In C and C++, concatenating two strings implies ignoring the terminating null character of the first string in the resultant string. Take a look at the documentation of strcat. It is explicit about the null character while the documentation of std::string::operator+ isn't.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

Not quite...

Let's take a look at this line:

a = a.c_str();

You have an std::string that you're trying to assign a const char* to. So you'll be using overload (3) of the std::string assignment operator. But this doesn't magically change the type of a. In other words, we still have an std::string!

So that line doesn't actually modify the value of a at all.

Then you use the operator+ to add two std::string's together. This will result in another std::string that is the first with the second appended, which is exactly what you have!

It's not clear to me what you're trying to accomplish here, but if you created a c-string with those values:

const char cstr[] = "Hello World\0aaa";

And tried to print it, you'd see exactly what you're expecting.

scohe001
  • 15,110
  • 2
  • 31
  • 51