Is a c-style string containing only one char considered a string? - c++

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

Related

Why does std::string("\x00") report length of 0?

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

null character inside string

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;
}

need help changing single character in char*

I'm getting back into c++ and have the hang of pointers and whatnot, however, I was hoping I could get some help understanding why this code segment gives a bus error.
char * str1 = "Hello World";
*str1 = '5';
ERROR: Bus error :(
And more generally, I am wondering how to change the value of a single character in a cstring. Because my understanding is that *str = '5' should change the value that str points to from 'H' to '5'. So if I were to print out str it would read: "5ello World".
In an attempt to understand I wrote this code snippet too, which works as expected;
char test2[] = "Hello World";
char *testpa2 = &test2[0];
*testpa2 = '5';
This gives the desired output. So then what is the difference between testpa2 and str1? Don't they both point to the start of a series of null-terminated characters?
When you say char *str = "Hello World"; you are making a pointer to a literal string which is not changeable. It should be required to assign the literal to a const char* instead, but for historical reasons this is not the case (oops).
When you say char str[] = "Hello World;" you are making an array which is initialized to (and sized by) a string known at compile time. This is OK to modify.
Not so simple. :-)
The first one creates a pointer to the given string literal, which is allowed to be placed in read-only memory.
The second one creates an array (on the stack, usually, and thus read-write) that is initialised to the contents of the given string literal.
In the first example you try to modify a string literal, this results in undefined behavior.
As per the language standard in 2.13.4.2
Whether all string literals are
distinct (that is, are stored in
nonoverlapping objects) is
implementation-defined. The effect of
attempting to modify a string literal
is undefined.
In your second example you used string-literal initialization, defined in 8.5.2.1
A char array (whether plain char,
signed char, or unsigned char) can be
initialized by a string- literal
(optionally enclosed in braces); a
wchar_t array can be initialized by a
wide string-literal (option- ally
enclosed in braces); successive
characters of the string-literal
initialize the members of the
array.

What does L do?

What does this do?
const wchar_t *s = L"test";
If wchar_t is two bytes on my machine, then why should we tell the compiler that the string should be treated in a way that each element is long i.e, four bytes in size?
The L means that string is a string of wchar_t characters, rather than the normal string of char characters. I'm not sure where you got the bit about four bytes from.
From the spec section 6.4.5 String literals, paragraph 2:
A character string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in "xyz". A wide string literal is the same, except prefixed by the letter L.
And an excerpt from paragraph 5:
For character string literals, the array elements have type char, and are initialized with the individual bytes of the multibyte character sequence; for wide string literals, the array elements have type wchar_t, and are initialized with the sequence of wide characters corresponding to the multibyte character
sequence, as defined by the mbstowcs function with an implementation-defined current locale.
If in doubt, consult the standard (ยง6.4.5, String Literals):
A character string literal is a
sequence of zero or more multibyte
characters enclosed in double-quotes,
as in "xyz". A wide string literal is
the same, except prefixed by the
letter L.
Note that it does not indicate that each character is a long, despite being prefixed with the same letter as the long literal suffix.
L does not mean long integer when prefixing a string. It means each character in the string is a wide character.
Without this prefix, you are assigning a string of char to a wchar_t pointer, which would be a mismatch.
It indicates a string of wide characters, of type wchar_t.
If you don't know what that L does, then why are you making an assertive statement about each array element being long ("four bytes in size")? Where did that idea with the long come from?
That L has as much relation to long as it has to "leprechaun" - no relation at all. The L prefix means that the following string literal consists of wide characters, i.e. each character has wchar_t type.
P.S. Finally, it is always a good idea to use const-qualified pointers when pointing to string literals: const wchar_t *s = L"test";.

How do I append a string to a char?

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.