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(©[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)
?
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.
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
ifn > 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 lengthn
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 lengthn
whose firstsize()
elements are a copy of the original string designated by*this
, and whose remaining elements are all initialized toc
.
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(©[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".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With