From Rules for C++ string literals escape character ,Eli's answer
std::string ("0\0" "0", 3) // String concatenation
works because this version of the constructor takes a char array; if you try to just pass "0\0" "0" as a const char*, it will treat it as a C string and only copy everything up until the null character.
Does that mean space isn't alloted for entire string , ie the string after \0 is written on unalloted space ?
Moreover the above question is for c++ string, I observed same behaviour for c strings too .
Are c and c++ strings same when I add null char in middle of string during declaration ?
The char array is copied into the new object. If you don't specify, how long the char array is, C++ will copy until the first null character. How much additional space is allocated is outside the scope of the specification. Like vectors, strings have a capacity that can exceed the amount required to store the string and allows to append characters without relocating the string.
std::string constructor that takes a const char* assumes the input is a C string.
C strings are '\0' terminated and thus stops when it reaches the '\0' character.
If you really want to play you need to use the constructor that builds the string from a
char array (not a C-String).
STL sequence containers exceed the amount required to store automatically
Example :
int main () {
string s="Elephant";
s[4] ='\0'; //C++ std::string is NOT '\0' terminated
cout<<s<<endl; //Elep ant
string x("xy\0ab"); // C-String assumed.
cout<<x; //xy
return 0;
}
Related
I have a function which needs to encode strings, which needs to be able to accept 0x00 as a valid 'byte'. My program needs to check the length of the string, however if I pass in "\x00" to std::string the length() method returns 0.
How can I get the actual length even if the string is a single null character?
std::string is perfectly capable of storing nulls. However, you have to be wary, as const char* is not, and you very briefly construct a const char*, from which you create the std::string.
std::string a("\x00");
This creates a constant C string containing only the null character, followed by a null terminator. But C strings don't know how long they are; so the string thinks it runs until the first null terminator, which is the first character. Hence, a zero-length string is created.
std::string b("");
b.push_back('\0');
std::string is null-clean. Characters (\0) can be the zero byte freely as well. So, here, there is nothing stopping us from correctly reading the data structure. The length of b will be 1.
In general, you need to avoid constructing C strings containing null characters. If you read the input from a file directly into std::string or make sure to push the characters one at a time, you can get the result you want. If you really need a constant string with null characters, consider using some other sentinel character instead of \0 and then (if you really need it) replace those characters with '\0' after loading into std::string.
You're passing in an empty string. Use std::string(1, '\0') instead.
Or std::string{ '\0' } (thanks, #zett42)
With C++14, you can use a string literal operator to store strings with null bytes:
using namespace std::string_literals;
std::string a = "\0"s;
std::string aa = "\0\0"s; // two null bytes are supported too
Is a c-style string containing only one char considered a string or would you call that construct a char?
Zero or more characters followed by a NUL-terminator is a C-style string. You can use the double quotation character notation to define a literal.
In C, an int that can fit into a char, such as '3' is a char.
Something like '34' is multicharacter literal.
A one element buffer is still technically a buffer. Forming a pointer to the start of it is not at all affected by how many items are in it.
So no, it's not a char. Furthermore, even the type system would differentiate char[1] from char.
It's also worth nothing that you may be surprised by what is a 1 character string. Because this one "a" has two characters in the buffer, not one. The only one character buffer that is a valid C-string is the empty string.
Is a c-style string containing only one char considered a string or
would you call that construct a char?
Indeed a C-Style string means a string i.e. it is quite different from a char data type. Since in C language, You don't have a dedicated built-in type to manipulate and represent string type like in C++ we have std::string hence once has to use character arrays (essentially null terminated) i.e. char str[SIZE] = "something" to represent character string type. On the other hand a single character is stored in char which is altogether different from char []. These two things are not same!
Example,
char str[] = "a"; // sizeof(str) will give 2 because presence of extra NULL character
char c = 'a'; // simply a single character
I'm using the XOR encryption so when I'm going to decrypt my string I need to get the length of that string.
I tried in this way:
string to_decode = "abcd\0lom";
int size = to_decode.size();
or in this way:
string to_decode = "abcd\0lom";
int size = to_decode.lenght();
Both are wrong because the string contain \0.
So how can I have the right length of my string?
The problem is with the initialisation, not with the size. If you use the constructor taking a const char *, it interprets that argument as a NUL-terminated string. So your std::string is only initialised with the string abcd.
You need to use a range-based constructor:
const char data[] = "abcd\0lom";
std::string to_decode(data, data + (sizeof data) - 1); // -1 to not include terminating NUL
[Live example]
However, be careful with such strings. While std::string can deal with embedded NULs perfectly fine, the result of c_str() will behave as "truncated" as far as all NUL-terminated APIs are concerned.
When you initialize the std::string, with a \0 in the middle, you loose all data ahead of it. If you think about it, a std::string is just a wrapper for a char*, and that gets terminated by a null termination \0. If the \0, doesn't have any meaning in the string, then you could escape it, like this:
string to_decode = "abcd\\0lom";
and the size would be 9. Otherwise, you could a container (eg: std::vector), of char's for the data storage
As others have said, the problem is that the code uses the constructor that takes const char*, and that only copies up to the \0. But, by a very strange coincidence, std::string has a constructor that can handle that case:
const char text[] = "abcd\0lom";
std::string to_decode(text, sizeof(text) - 1);
int size = to_decode.size();
The constructor will copy as many characters as you tell it to.
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 do I append a string to a char?
strcat(TotalRam,str);
is what i got but it does not support strings
std::String has a function called c_str(), that gives you a constant pointer to the internal c string, you can use that with c functions. (but make a copy first)
Use + on strings:
std::string newstring = std::string(TotalRam) + str;
If you want it as a char[] instead, you need to allocated memory on the heap or stack first. After that, strcat or sprintf are possible options.
You can't append a string to a char, you can only append a string to a string (or a char* if using the C string functions). In your example, you'll have to copy (the char) TotalRam into a string of some sort, either a C++ std::string, or make a char[2] to hold it and the required terminating NULL character. Then you can either use the C++ string with C++ functions or the char[2] with strcat and friends.
for performance, do this:
char ministring[2] = {0,0};
// use ministring[0] as your char, fill it in however you like
strcat(ministring,str);
The char array is stack-allocated so it is extremely fast, and the second char with the value of zero acts as a string terminator so that functions like strcat will treat it as a 'c' string.