-1

Let's suppose I create a string like this:

std::string s1 = "";
s1 += 'a';
s1 += 'b';

And then one like this:

std::string s2 = std::string( "ab" );

Are s1 and s2 equal? Is the \0 stripped from "ab" when creating s2? If not, is there an easy (one-line, preferably) way to check if s1 contains only and exactly {'a', 'b'}?

cyangekko
  • 17
  • 1
  • 1
    if you want to know if `s1` and `s2` are equal, you can just check it yourself: `bool are_equal = s1 == s2;` – jalf May 11 '15 at 07:18

2 Answers2

2

Are s1 and s2 equal?

Yes.

Is the \0 stripped from "ab" when creating s2?

That's not really a meaningful question. The code that constructs s2 can construct if however it wants. It can copy the terminator, remove it, leave it, whatever it wants. It just has to know how to find the end of the C-style string, and it does.

If not, is there an easy (one-line, preferably) way to check if s1 contains only and exactly {'a', 'b'}?

if (s1 == "ab")

The string class has an operator== that does what you probably expect, comparing the values for equivalence. It understands how both C-style and C++-style strings work and so can compare their values.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • The null byte *is* stripped. As in, it is not part of the string. The string is guaranteed to have length 2, and contain the two characters a and b and nothing else. The buffer may well be null-terminated, but the string does not contain the null byte. – jalf May 11 '15 at 07:20
  • 1
    @jalf I'm not sure that it's meaningful to say the "string does not contain the null byte". Its value doesn't, but that's (arguably) true for a C-style string too. The important thing is that it doesn't matter -- how C++-style strings are terminated or store their length is unspecified and irrelevant. – David Schwartz May 11 '15 at 07:21
  • 2
    StackOverflow consensus seems to be that in C++11 `std::string`s are indeed null-terminated due to the requirements on `c_str`. – filmor May 11 '15 at 07:23
  • @jalf As for the string being guaranteed to have length 2, so what? If you do `const char * j = "ab";` it's guaranteed that `strlen(j)` is 2. Does that make it sensible to say the string does not contain the null byte? – David Schwartz May 11 '15 at 07:23
  • They are equal, but not identical. Equal means `operator==` evaluates to true, in this case it means the characters of the string are the same. Identical would mean `&s1 == &s2`, i.e. `s1` and `s2` refer to the same object. Here it is never the case because they are two variables on the stack, it could be if they were references. – tmlen May 11 '15 at 07:26
  • @filmor: That's the difference between what is *specified*, and what is *common implementation*. Software that's written against the latter is the stuff that tends to break in the most unfortunate moment in the future because one of the assumptions no longer holds true. Do not assume. Stick with the specs. – DevSolar May 11 '15 at 07:30
  • @filmor according to [this](http://stackoverflow.com/questions/11752705/does-string-contain-null-terminator) `\0` isn't special for `std::string`s. – cyangekko May 11 '15 at 07:33
  • @cyangekko `\0` inside the string is a completely different issue. – David Schwartz May 11 '15 at 07:35
  • 1
    @DavidSchwartz but a `std::string` can't be null-terminated if `\0` has no significance, right? Otherwise inserting `\0` into the middle of the string would cut it short. – cyangekko May 11 '15 at 07:44
  • 2
    @cyangekko It can be nul-terminated in the sense that it can have a zero byte at the end of it. It just can't be null-terminated in the sense that you can determine its "true end" by scanning it for a nul. The same is true of C-style strings -- `const char *j = "a\0b;"`. You can think of this as a three-byte string terminated with a nul, but of course you can't determine its true length by scanning it for one. – David Schwartz May 11 '15 at 08:02
  • 1
    @DevSolar It is not. I'm well aware of that distinction and that's why I explicitly referred to C++11. In C++98/03 the standard did not ensure this, because IIRC `c_str` was allowed to copy the data around. Check http://stackoverflow.com/questions/7554039/is-stringc-str-no-longer-null-terminated-in-c11 for example. – filmor May 11 '15 at 08:07
  • 1
    A `std::string` is not null-terminated in the sense that its end is not determined by the null byte. Its end is determined by the end iterator (or the string's length). The null byte is there solely in order to faciliate the conversion to a C-style string, but it is not significant in and of itself, and it is not part of the string's value. – jalf May 11 '15 at 19:39
0

It is easy to determine what happens by using method size().

For example after creating an object like this

std::string s1 = "";

the size of s1 will be equal to 0.

Here is called constructor

basic_string(const charT* s, const Allocator& a = Allocator());

that copies characters from an array first element of which is pointed to by s. As the length of string literal "" is equal to 0 then the constructed object also does not have elements and its size is equal to 0.

After these statements

s1 += 'a';
s1 += 'b';

the object will contain two characters 'a' and 'b'. Thus the object will be equal to the object constructed like std::string( "ab" );.

Take into account for example if you have a character array defined like

char s[] = { 'a', 'b', '\0', 'c', 'd', '\0' };

and will use to construct an object of type std::string like this

std::string s1( s );

then s1 will contain only two elements 'a' and 'b' and its size will be equal to 2.

It will be useful to consider another example. Let's assume that you wrote

std::string s1 = "";

and then

s1 += 'a';
s1 += 'b';
s1 += '\0';

In this case s1 will not be equal to object std::string( "ab" ) because the size of s1 is now equal to 3.

Another interesting example. You can use constructor

basic_string(const charT* s, size_type n, const Allocator& a = Allocator());

It is similar to the previous constructor except it allows to specify explicitly the number of characters in the character array pointed to by pointer s that will be used to construct an object of type std::string. In this case if you will write

std::string s1( "ab", 3 );
std::cout << s1.size() << std::endl;

if ( s1 == std::string( "ab" ) ) std::cout << "They are equal" << std::endl;
else std::cout << "They are not equal" << std::endl;

then the output will be

3
They are not equal

At the same time if you will write

std::cout << s1 << std::endl;

you will see

ab
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335