Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the std::string::resize() method manages the terminating character?

Tags:

c++

string

c++11

I am copying some data from a stream into a string, so I thought about resizing the string with the actual number of characters plus one for the terminating one, like this:

std::istringstream stream { "data" };
const std::size_t count = 4;

std::string copy;
copy.resize(count + 1);

stream.read(&copy[0], count);
copy[count] = 0;

However, in this case, copy indicates it has a size of 5 (which is consistent since I called resize(5)). Does that mean that resize() will add the extra terminating character itself? Which would mean that I do not have to worry about appending \0 after invoking read(&data[0], count)?

like image 619
piwi Avatar asked Dec 26 '22 06:12

piwi


2 Answers

No you don't have to. The string class abstracts the concept of "null terminated char sequence", so that you don't have to worry about that anymore.

Also, the size of the string returned doesn't count the terminating character, which is consistent with the behavior I mentioned, because if you don't have to deal with the terminating character, you don't have to know about it. Your string is just the characters you want to manipulate, without any concern for that "utility" character that has nothing to do with your actual data.

like image 200
JBL Avatar answered Mar 15 '23 13:03

JBL


The quote §21.4.7.1 basic_string accessors [string.accessors] from the standard indicates that std::string has a guaranteed null terminated buffer.

Also according to the standard §21.4.4/6-8 basic_string capacity [string.capacity]:

void resize(size_type n, charT c);

6 Requires: n <= max_size()

7 Throws: length_error if n > max_size().

8 Effects: Alters the length of the string designated by *this as follows:

- If n <= size(), the function replaces the string designated by *this with a string of length n whose elements are a copy of the initial elements of the original string designated by *this.

- If n > size(), the function replaces the string designated by *this with a string of length n whose first size() elements are a copy of the original string designated by *this, and whose remaining elements are all initialized to c.

void resize(size_type n);

9 Effects: resize(n,charT()).

Interpreting the above std::string::resize will not affect the terminating null character of the string's buffer.

Now to your code:

statement std::string copy; defines an empty string (i.e., copy.size() == 0).

statement copy.resize(count + 1); since (n == 5) > 0 will replace copy with a string of length 5 filled with \0 (i.e., null characters).

Now in statement stream.read(&copy[0], count); std::stream::read will simply copy a block of data, without checking its contents nor appending a null character at the end.

In other words it will just replace the first 4 null characters of copy with "data". The size of copy won't change it will be still a 5 sized string. That is, the contents of copy's buffer will be "data\0\0".

So calling copy[count] = 0; is redundant since copy[4] is already \0. However, your string is not "data" but rather "data\0".

like image 33
101010 Avatar answered Mar 15 '23 11:03

101010