Dynamic length of strings in C++ - c++

I've debugged some programs in C++ and I notice a difference between for instance :
char str[] = "It's a test";
But when you use string in <string> header, it seems that has a variable length and for instance, the following is allowed:
string str1 = "abcdefg";
str1 = "abc";
But this is not allowed :
char str[] = "It's a test";
str = "abc";
It won't work! What's the implementation behind that?

You can initialize an array, which is done with
char array[] = "some string literal";
but you can't assign to an array. That's just the rules of the language.
The std::string class have a special overload for the assignment operator that allows it to be assigned to.

you thought that when at first you have initialised the array of characters and another time when you use it it is not needed to initialise again! but its not true...every time you declare and initialise any array and when ever you are using it again you have to do it again! for example:
char user[] = "sci3nt15t";
char user[] = "Ender";
its good for you to have a look at a definition of string and array.
hope it helps.

Related

How to convert a string type to an array of chars

I'm trying to translate some C code to D, and I've come across this:
char[] welcome = "\t\tWelcome to the strange land of protected mode!\r\n";
It gives this warning:
main.d:5:18: error: cannot implicitly convert expression ("\x09\x09Welcome to the strange land of protected mode!\x0d\x0a") of type string to char[]
5 | char[] welcome = "\t\tWelcome to the strange land of protected mode!\r\n";
| ^
How do I do this without typing each character out individually in the array?
As already mentioned, strings already are an array of chars. In fact, here is the definition of string:
alias string = immutable(char)[];
(from object.d)
A string thus differs from a char[] only in that the contents of the array is immutable.
Depending on your goal, you may not need a char[] after all, and string will work as well.
If you need the array to be writable (i.e. you expect welcome[2] = 'x'; to work), then using .dup will create a copy at runtime.
Sometimes C function declarations are not properly annotated with const, and will not accept pointers to immutable characters. In this case, using a cast is acceptable.
I don't think there is a language feature to place a string literal directly in a writable data segment, in the same way that static char[] s = ['a', 'b', 'c']; does, but it's likely doable as a template or CTFE function.
12.16.1 - Strings
A string is an array of characters. String literals are just an easy way to write character arrays. String literals are immutable
(read only).
char[] str1 = "abc"; // error, "abc" is not mutable
char[] str2 = "abc".dup; // ok, make mutable copy
immutable(char)[] str3 = "abc"; // ok
immutable(char)[] str4 = str1; // error, str4 is not mutable
immutable(char)[] str5 = str1.idup; // ok, make immutable copy
The name string is aliased to immutable(char)[], so the above declarations could be equivalently written as:
char[] str1 = "abc"; // error, "abc" is not mutable
char[] str2 = "abc".dup; // ok, make mutable copy
string str3 = "abc"; // ok
string str4 = str1; // error, str4 is not mutable
string str5 = str1.idup; // ok, make immutable copy
So:
char[] welcome = "\t\tWelcome to the strange land of protected mode!\r\n".dup;

expression must have class type error c++

So I have this defined:
static char randomstring[128];
Now whenever I mention it somewhere like so:
char *x = randomstring;
It goes fine but whenever I try to do something with its content:
char *x = ranomstring.front();
It doesn't work at all and says expression must have class type..
This problem occurs a LOT for me.
I should also mention I'm a total noob at c++.
You should probably learn the difference betwenn std::string (a class) and c-style string (char* or char[] - array).
//this calls std::string constructor to convert c-style string to std::string:
string mystring = "hello world!";
//std::string has front()
char* front = mystring.front();
//this is old-style string
char oldstring[] = "hello again!";
//you can access it as pointer, not as class
char* first = oldstring;
//but you can iterate both
for(char c : mystring) cout << c;
for(char c : oldstring) cout << c;
//...because it uses std::begin which is specialized for arrays
Arrays in C++ are not classes. They are aggregates. So they have no methods.
Use instead either standard container std::string or standard container std::vector that can dynamically change their sizes and have method front.
For example
#include <string>
//...
std::string randomstring;
//filling the string
char x = randomstring.front();
Change char *x = ranomstring.front();
To char *x = ((string)ranomstring).front();

Why can't I write to a string literal while I *can* write to a string object?

If i define something like below,
char *s1 = "Hello";
why I can't do something like below,
*s1 = 'w'; // gives segmentation fault ...why???
What if I do something like below,
string s1 = "hello";
Can I do something like below,
*s1 = 'w';
Because "Hello" creates a const char[]. This decays to a const char* not a char*. In C++ string literals are read-only. You've created a pointer to such a literal and are trying to write to it.
But when you do
string s1 = "hello";
You copy the const char* "hello" into s1. The difference being in the first example s1 points to read-only "hello" and in the second example read-only "hello" is copied into non-const s1, allowing you to access the elements in the copied string to do what you wish with them.
If you want to do the same with a char* you need to allocate space for char data and copy hello into it
char hello[] = "hello"; // creates a char array big enough to hold "hello"
hello[0] = 'w'; // writes to the 0th char in the array
string literals are usually allocated in read-only data segment.
Because Hello resides in read only memory. Your signature should actually be
const char* s1 = "Hello";
If you want a mutable buffer then declare s1 as a char[]. std::string overloads operator [], so you can index into it, i.e., s1[index] = 'w'.
Time to confuse matters:
char s0[] = "Hello";
s0[0] = 'w';
This is perfectly valid! Of course, this doesn't answer the original question so here we go: string literals are created in read-only memory. That is, their type is char const[n] where n is the size of the string (including the terminating null character, i.e. n == 6 for the string literal "Hello". But why, oh, why can this type be used to initialize a char const*? The answer is simply backward compatibility, respectively compatibility to [old] C code: by the time const made it into the language, lots of places already initialized char* with string literals. Any decent compiler should warn about this abuse, however.

C++ converting string to char is not working

I have the following code to convert a string to char :
string tempLine = dataLine[studentIndex];
char str = tempLine.c_str();
but this line returns an error : " a value of type "constant char *" cannot be used to initialize an entity of type "char".
How can I fix this issue??
should be:
const char *str = tempLine.c_str();
Note that you're not supposed to change the content of the string. Generally, its not a good way to work with C++ strings. If you really have to fully convert a C++ string to C string - allocate memory and use strcpy to copy data, don't use the C++ string buffers directly.
edit for your request in the comments: Look here for C++ learning resources.
You cannot convert a const char*, which is what std::string::c_str() returns, to char. Change:
char str = tempLine.c_str();
to:
const char* str = tempLine.c_str();
Note this does not copy the characters in tempLine to str, str just refers to the characters in tempLine.

How to assign a string to char *pw in c++

How to assign a string to a char* (char pointer) in C++?
char *pw = some string
For constant initialization you can simply use
const char *pw = "mypassword";
if the string is stored in a variable, and you need to make a copy of the string then you can use strcpy() function
char *pw = new char(strlen(myvariable) + 1);
strcpy(pw, myvariable);
// use of pw
delete [] pw; // do not forget to free allocated memory
If you just want to assign a string literal to pw, you can do it like char *pw = "Hello world";.
If you have a C++ std::string object, the value of which you want to assign to pw, you can do it like char *pw = some_string.c_str(). However, the value that pw points to will only be valid for the life time of some_string.
If you mean a std::string, you can get a pointer to a C-style string from it, by calling c_str. But the pointer needs to be const.
const char *pw = astr.c_str();
If pw points to a buffer you've previously allocated, you might instead want to copy the contents of a string into that buffer:
astr.copy(pw, lengthOfBuffer);
If you're starting with a string literal, it's already a pointer:
const char *pw = "Hello, world".
Notice the const again - string literals should not be modified, as they are compiled into your program.
But you'll have a better time generally if you use std::string everywhere:
std::string astr("Hello, world");
By the way, you need to include the right header:
#include <string>
I think you may want to do this:
using namespace std;
string someString;
geline(cin,someString);
char *pw = strdup(someString.c_str());
But consider doing it another way. Check out http://tiswww.case.edu/php/chet/readline/rltop.html (GNU Readline library). I don't know details about it, just heard about it. Others may have more detailed or other tips for reading passwords from standard input.
If you only want to use it for a single call for something you do not need to copy the contents of someString, you may use someString.c_str() directly if it is required as const char *.
You have to use free on pw some time later,
String must be enclosed in double quotes like :
char *pStr = "stackoverflow";
It will store this string literal in the read only memory of the program.
And later on modification to it may cause UB.