Does std::string have a null terminator? - c++

Will the below string contain the null terminator '\0'?
std::string temp = "hello whats up";

No, but if you say temp.c_str() a null terminator will be included in the return from this method.
It's also worth saying that you can include a null character in a string just like any other character.
string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';
prints
5 5
and not 5 1 as you might expect if null characters had a special meaning for strings.

Not in C++03, and it's not even guaranteed before C++11 that in a C++ std::string is continuous in memory. Only C strings (char arrays which are intended for storing strings) had the null terminator.
In C++11 and later, mystring.c_str() is equivalent to mystring.data() is equivalent to &mystring[0], and mystring[mystring.size()] is guaranteed to be '\0'.
In C++17 and later, mystring.data() also provides an overload that returns a non-const pointer to the string's contents, while mystring.c_str() only provides a const-qualified pointer.

This depends on your definition of 'contain' here. In
std::string temp = "hello whats up";
there are few things to note:
temp.size() will return the number of characters from first h to last p (both inclusive)
But at the same time temp.c_str() or temp.data() will return with a null terminator
Or in other words int(temp[temp.size()]) will be zero
I know, I sound similar to some of the answers here but I want to point out that size of std::string in C++ is maintained separately and it is not like in C where you keep counting unless you find the first null terminator.
To add, the story would be a little different if your string literal contains embedded \0. In this case, the construction of std::string stops at first null character, as following:
std::string s1 = "ab\0\0cd"; // s1 contains "ab", using string literal
std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr
std::string s3 = "ab\0\0cd"s; // s3 contains "ab\0\0cd", using ""s operator
References:
https://akrzemi1.wordpress.com/2014/03/20/strings-length/
http://en.cppreference.com/w/cpp/string/basic_string/basic_string

Yes if you call temp.c_str(), then it will return null-terminated c-string.
However, the actual data stored in the object temp may not be null-terminated, but it doesn't matter and shouldn't matter to the programmer, because when then programmer wants const char*, he would call c_str() on the object, which is guaranteed to return null-terminated string.

With C++ strings you don't have to worry about that, and it's possibly dependent of the implementation.
Using temp.c_str() you get a C representation of the string, which will definitely contain the \0 char. Other than that, i don't really see how it would be useful on a C++ string

std::string internally keeps a count of the number of characters. Internally it works using this count. Like others have said, when you need the string for display or whatever reason, you can its c_str() method which will give you the string with the null terminator at the end.

Related

in the C ++ stl, does the string container actually contain a string with a closing 0? [duplicate]

Will the below string contain the null terminator '\0'?
std::string temp = "hello whats up";
No, but if you say temp.c_str() a null terminator will be included in the return from this method.
It's also worth saying that you can include a null character in a string just like any other character.
string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';
prints
5 5
and not 5 1 as you might expect if null characters had a special meaning for strings.
Not in C++03, and it's not even guaranteed before C++11 that in a C++ std::string is continuous in memory. Only C strings (char arrays which are intended for storing strings) had the null terminator.
In C++11 and later, mystring.c_str() is equivalent to mystring.data() is equivalent to &mystring[0], and mystring[mystring.size()] is guaranteed to be '\0'.
In C++17 and later, mystring.data() also provides an overload that returns a non-const pointer to the string's contents, while mystring.c_str() only provides a const-qualified pointer.
This depends on your definition of 'contain' here. In
std::string temp = "hello whats up";
there are few things to note:
temp.size() will return the number of characters from first h to last p (both inclusive)
But at the same time temp.c_str() or temp.data() will return with a null terminator
Or in other words int(temp[temp.size()]) will be zero
I know, I sound similar to some of the answers here but I want to point out that size of std::string in C++ is maintained separately and it is not like in C where you keep counting unless you find the first null terminator.
To add, the story would be a little different if your string literal contains embedded \0. In this case, the construction of std::string stops at first null character, as following:
std::string s1 = "ab\0\0cd"; // s1 contains "ab", using string literal
std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr
std::string s3 = "ab\0\0cd"s; // s3 contains "ab\0\0cd", using ""s operator
References:
https://akrzemi1.wordpress.com/2014/03/20/strings-length/
http://en.cppreference.com/w/cpp/string/basic_string/basic_string
Yes if you call temp.c_str(), then it will return null-terminated c-string.
However, the actual data stored in the object temp may not be null-terminated, but it doesn't matter and shouldn't matter to the programmer, because when then programmer wants const char*, he would call c_str() on the object, which is guaranteed to return null-terminated string.
With C++ strings you don't have to worry about that, and it's possibly dependent of the implementation.
Using temp.c_str() you get a C representation of the string, which will definitely contain the \0 char. Other than that, i don't really see how it would be useful on a C++ string
std::string internally keeps a count of the number of characters. Internally it works using this count. Like others have said, when you need the string for display or whatever reason, you can its c_str() method which will give you the string with the null terminator at the end.

Is it valid for an std::string to contain a null character '\0' not at its end? [duplicate]

For regular C strings, a null character '\0' signifies the end of data.
What about std::string, can I have a string with embedded null characters?
Yes you can have embedded nulls in your std::string.
Example:
std::string s;
s.push_back('\0');
s.push_back('a');
assert(s.length() == 2);
Note: std::string's c_str() member will always append a null character to the returned char buffer; However, std::string's data() member may or may not append a null character to the returned char buffer.
Be careful of operator+=
One thing to look out for is to not use operator+= with a char* on the RHS. It will only add up until the null character.
For example:
std::string s = "hello";
s += "\0world";
assert(s.length() == 5);
The correct way:
std::string s = "hello";
s += std::string("\0world", 6);
assert(s.length() == 11);
Storing binary data more common to use std::vector
Generally it's more common to use std::vector to store arbitrary binary data.
std::vector<char> buf;
buf.resize(1024);
char *p = &buf.front();
It is probably more common since std::string's data() and c_str() members return const pointers so the memory is not modifiable. with &buf.front() you are free to modify the contents of the buffer directly.
Yes. A std::string is just a vector<char> with benefits.
However, be careful about passing such a beast to something that calls .c_str() and stops at the 0.
You can, but why would you want to? Embedding NUL in an std::string is just asking for trouble, because functions to which you pass an std::string may very well use it's c_str() member, and most will assume that the first NUL indicates the end of the string. Hence this is not a good idea to do. Also note that in UTF-8, only '\0' will result in a 0, so even for i18n purposes, there is no justification for embedding NULs.
Yep this is valid.
You can have a null character in the middle of the string.
However, if you use a std::string with a null character in the middle with a c string
function your in undefined behaviour town - and nobody wants to be there!!!:
int n = strlen( strWithNullInMiddle.c_str() ); // Boom!!!

Count of bytes in std::string [duplicate]

Im using BSPlib and I want to use the bsp_put which requires me to set the size of the string I'm sending.
Even if you aren't familiar with BSP, this is not closely related. thanks.
Multiply the number of characters (given by size(), or capacity() if you want to know the total amount allocated rather than the amount in use) by the size of the character type.
If it's std::string itself, an alias for std::basic_string<char>, then the character size is one byte, so size() (or capacity()) alone will do.
strlen returns the length of string of a plain C string.
A C string is as long as the amount of characters between the beginning of the string and the terminating null character.
If you're using the String object you can use the length or size method of the object:
http://www.cplusplus.com/reference/string/string/length/
The number of characters in a std::string can be had by the "size()" member of std::string.
std::string s = "Hey, look, I'm a string!"
std::string::size_type len = s.size();
std::cout << "My string is " << len << "characters long." << std::endl;
As people have pointed out, you cannot rely upon the memory organization of std::string, except for two cases: std::string::data() and std::string::c_str(). Each of these functions return a pointer to contiguous memory, which memory holds the same characters as the string. (The memory may or may not point to the real string, but it doesn't matter, you can't write to it anyway.) The difference between the two calls is whether the memory has a terminating null byte: data() has no terminating character, c_str() does.
// assuming that bsp_put_bytes takes a pointer & len
bsp_put_bytes(s.data(), s.size());
// and bsp_put_string takes a C-style string
bsp_put_string(s.c_str());
Carefully read the caveats in the links I gave you, including the valid lifetime of the pointed-to characters.
std::string myString("this is the text of my string");
const char *copyOfString = strdup(myString.c_str());
size_t myStringLength = strlen(copyOfString);
free(copyOfString);
That's probably the most efficient way of getting the length of the string. Let me know how impressed your coworkers are when you show them your new solution using this example.

strncpy to already created char []

There is class
class Cow{
char name[20];
char* hobby;
double weight;
public:
[..]
Cow & operator=(const Cow &c);
[..]
};
and I'm wondering how to write definition of operator= method.
I wrote definition that equal to -
Cow & Cow::operator=(const Cow &c){
if(this==&c)
return *this;
delete [] hobby;
hobby=new char [strlen(c.hobby)+1];
weight=c.weight;
strncpy(name,c.name,20);
return *this;
}
but what if there is already created name[20] with like "Philip Maciejowsky" and I strncpy to it "Adam". After operator=(...) will name equal to "adamlip Maciejowsky"?
How to fix it if it overwrites like that?
Use strcpy() or add a null terminator after using strncpy(). strncpy() does not add the null terminator (\0), where as strcpy() does.
My advice: use std::string instead of c-styled null terminated string.
when in rome, do the romans!
From http://cplusplus.com
No null-character is implicitly appended at the end of destination if source is longer than >num (thus, in this case, destination may not be a null terminated C string).
Since Adam is lesser in length than Philip Maciejowsky - the strncpy() will NOT pad the remaining destination(that is Philip Maciejowsky) with \0. And hence the output looks like:
Adamip Maciejowsky - strcpy() or doing memset(destination, 0, lengthOfDestination) and then calling strncpy() will result in your output being Adam as well. Multiple ways to do what you're trying to do.
First, if you're using C++ you shouldn't be using C-style strings and should instead be using the class std::string which makes everything easier in every way.
Assuming you're required to use char* strings, strncpy takes care of this. C-style string are null-terminated, meaning that a string such as "test" takes up five bytes. The bytes are, in order, {'t', 'e', 's', t', 0}. The zero (or null) byte serves as a marker that the end of the string has been reached.
From the manpage for strncpy on my system:
The following sets chararray to abc\0\0\0:
char chararray[6];
(void)strncpy(chararray, "abc", sizeof(chararray));
So this means that the string will contain "adam\0\0\0\0\0\0\0[etc.]" where \0 represents the null byte. String functions will stop processing when they read the first null (because, remember, with C-style strings, there's no way to know the length of the string without scanning through it looking for \0).

How to get the number of bytes occupied by a specific string in the program?

Im using BSPlib and I want to use the bsp_put which requires me to set the size of the string I'm sending.
Even if you aren't familiar with BSP, this is not closely related. thanks.
Multiply the number of characters (given by size(), or capacity() if you want to know the total amount allocated rather than the amount in use) by the size of the character type.
If it's std::string itself, an alias for std::basic_string<char>, then the character size is one byte, so size() (or capacity()) alone will do.
strlen returns the length of string of a plain C string.
A C string is as long as the amount of characters between the beginning of the string and the terminating null character.
If you're using the String object you can use the length or size method of the object:
http://www.cplusplus.com/reference/string/string/length/
The number of characters in a std::string can be had by the "size()" member of std::string.
std::string s = "Hey, look, I'm a string!"
std::string::size_type len = s.size();
std::cout << "My string is " << len << "characters long." << std::endl;
As people have pointed out, you cannot rely upon the memory organization of std::string, except for two cases: std::string::data() and std::string::c_str(). Each of these functions return a pointer to contiguous memory, which memory holds the same characters as the string. (The memory may or may not point to the real string, but it doesn't matter, you can't write to it anyway.) The difference between the two calls is whether the memory has a terminating null byte: data() has no terminating character, c_str() does.
// assuming that bsp_put_bytes takes a pointer & len
bsp_put_bytes(s.data(), s.size());
// and bsp_put_string takes a C-style string
bsp_put_string(s.c_str());
Carefully read the caveats in the links I gave you, including the valid lifetime of the pointed-to characters.
std::string myString("this is the text of my string");
const char *copyOfString = strdup(myString.c_str());
size_t myStringLength = strlen(copyOfString);
free(copyOfString);
That's probably the most efficient way of getting the length of the string. Let me know how impressed your coworkers are when you show them your new solution using this example.