I am facing an issue with string and null characters in C . When I am writing '\0' in between the string and printing the string then I am getting only part before '\0' but on the other hand when I am taking string as input then changing any index as '\0' then it is printing differently. Why is it so and why the sizeof(string) is 32 in both the cases Code is below for reference. Please help.
First code:
#include<iostream>
using namespace std;
int main(){
string s = "he\0llo";
cout<<s.length()<<"\n";
cout<<s<<endl;
cout<<sizeof(s)<<"\n";
}
output of First code:
2\n
he\n
32\n
Second code
#include<iostream>
using namespace std;
int main(){
string s;
cin>>s;
s[1] = '\0';
cout<<s<<"\n";
cout<<s.length()<<"\n";
cout<<sizeof(s)<<"\n";
return 0;
}
output of second code:
hllo\n
5\n
32\n
Below is the image for your reference.
CodePudding user response:
std::string
's implicit const CharT*
constructors and assignment operator don't know the exact length of the string argument. Instead, it only knows that this is a const char*
and is forced to assume that the string will be null-terminated, and thus computes the length using std::char_traits::length(...)
(effectively std::strlen
).
As a result, constructing a std::string
object with an expression like:
std::string s = "he\0llo";
will compute 2
as the length of the string, since it assumes the first \0
character is the null terminator for the string, whereas your second example of:
s[1] = '\0';
is simply adding a null character into an already constructed string -- which does not change the size of the string.
If you want to construct a string with a null character in the middle, you can't let it compute the length of the string for you. Instead, you will have to construct the std::string
and give it the length in some other way. This could either by done with the string(const char*, size_t)
constructor, or with an iterator pair if this is an array:
// Specify the length manually
std::string s{"he\0llo",6};
// Using iterators to a different container (such as an array)
const char c_str[] = "he\0llo";
std::string s{std::begin(c_str), std::end(c_str)};
Note: sizeof(s)
is telling you the size of std::string
class itself in bytes for your implementation of the standard library. This does not tell you the length of the contained string -- which can be determined from either s.length()
or s.size()
.
CodePudding user response:
As of c 14, there is an option to specify quoted strings as a std::string by using std::literals. This prevents conversion of an array of chars to string which automatically stops at the first nul character.
#include<iostream>
#include <string>
using namespace std;
using namespace std::literals;
int main() {
string s = "he\0llo"s; // This initializes s to the full 6 char sequence.
cout << s.length() << "\n";
cout << s << endl;
cout << sizeof(s) << "\n"; // prints size of the s object, not the size of its contents
}
Results:
6
hello
28