Char array gives error when initializing - c++

It can be simple but I m new about c++
In char arrays we can let the compiler to count number of characters in the string like
char myarray[]="stringvar";
its ok, but if i change the code as below,the compiler gives error
string myvar = "stringvar";
char myarray[] =myvar;
error: initializer fails to determine size of myarray
Why is that?

You can do this:
string myvar = "stringvar";
const char * myarray = myvar.c_str(); //immutable string
In this case, the data whichmyarray points to, lives as long as the lifetime of myvar.
However, if you want a mutable string or, a string which may last longer (or shorter) than the lifetime of myvar, then you've to allocate memory yourself as:
char * myarray = new char[myvar.size()+1]; //mutable string
std::strcpy(myarray, myvar.c_str());
//you've to deallocate the memory yourself as:
delete [] myarray;

You cannot assign an std::string object to initialize and create a character array.
You will need to copy the std::string in to the array.
strcpy(myarray,myvar.c_str());

There is error, because char myarray[] is equivalent to char* myarray. It is just a pointer to char. So you need a compatible initializer there (like char* or const char*). But you are trying to pass an instance of string class, that is not a pointer.
If you wish to assign myarray to a string (make it point to the same location) you may do this
char myarray[] = const_cast<char[]> myvar.c_str();
But in any case, its not good idea, until you definitely know what you're doing.

string myvar = "stringvar"
char* myarray = (char*)myvar.c_str();
It should work.

Related

Passing non-const char array to function as const char array is possible?

I was working with the strcmp function in C, then i saw the function as arguments gets:
strcmp(_const char *s1, const char *s2)_;
And actually i passed normal char array and it worked. Any ideas why this happening?
If you have for example the following code
char c = 'A';
char *p = &c;
const char *cp = &c;
then it means that you can change variable c using pointer p but you may not change it using pointer cp
For example
*p = 'B'; // valid assignment
*cp = 'B'; // compilation error
Thus function declaration
int strcmp(const char *s1, const char *s2);
means that inside the function the strings pointed to by s1 and s2 will not be changed.
There are two ways to use const key word to a pointer:
int my_int = 3;
const int* pt = &my_int; //prevent to modify the value that pointer pt points to
int* const ps = &my_int; //prevent to modify the value of pointer ps:
//it means the pointer is a const pointer, you can't modify the value of the pointer
//The value of the pointer ps is a memory address, so you can't change the memory address
//It means you can't reallocate the pointer(point the pointer to another variable)
int new_int = 5;
*pt = &new_int; //valid
*pt = 10; //invalid
*ps = &new_int; //invalid
*ps = 10; //valid
In strcmp function, the two arguments are pointer points to a const value, it means when you pass two char arrays or char pointers to the strcmp function, the function can use the value of those two pointers point to, but the function can't modify the value that you pass to it. That's why it works.
The const reference works in a similar way.
This worked, because passing non-const in place of const is allowed. It is the other way around that is prohibited:
char *hello = new char[20];
char *world= new char[20];
strcpy(hello, "hello");
strcpy(world, "world");
if (!strcmp(hello, world)) {
...
}
The const in the declaration is meant to tell the users of the API that the function will not modify the content of the string. In C++ this is important, because string literals are const. Without the const in the API, this call would have been prohibited:
if (!strcmp(someString, "expected")) { // <<== This would not compile without const
...
}
I think you intend to ask the mechanism of how the variable can compare the array.
if that's the case,
The pointer that has been declared in your example stores the initial address of the array's first element and
the ending point of the string can be determined by the detection null character that which in turn is the ending address of the array.
With that said the strcmp when called the pointer points to the strings or the character passed that is, the command would be assumed as follows strcmp("string1","string2");
and thus the comparison takes place as usual.
hmm i guess by this and with other examples posted around you can get a better picture for your answer.

how to initialize string pointer?

I want to store the static value in string pointer is it posible?
If I do like
string *array = {"value"};
the error occurs
error: cannot convert 'const char*' to 'std::string*' in initialization
you would then need to write
string *array = new string("value");
although you are better off using
string array = "value";
as that is the intended way to use it. otherwise you need to keep track of memory.
A std::string pointer has to point to an std::string object. What it actually points to depends on your use case. For example:
std::string s("value"); // initialize a string
std::string* p = &s; // p points to s
In the above example, p points to a local string with automatic storage duration. When it it gets destroyed, anything that points to it will point to garbage.
You can also make the pointer point to a dynamically allocated string, in which case you are in charge of releasing the resources when you are done:
std::string* p = new std::string("value"); // p points to dynamically allocated string
// ....
delete p; // release resources when done
You would be advised to use smart pointers instead of raw pointers to dynamically allocated objects.
As array is an array of strings you could try this:
int main()
{
string *array = new string[1];
array[1] = "value";
return 0;
}
You can explicitly convert the literal to a string:
std::string array[] = {std::string("value")};
Note that you have to define this as an array, not a pointer though. Of course, an array mostly makes sense if you have more than one element, like:
string array[] = {string("value1"), string("value2"), string("etc")};

Converting from std::vector<> to a double pointer?

I was wondering out of curiosity if it is possible to cast a std::vector<> to a double pointer.
I've never had an issue passing a std::vector as a pointer in this fashion:
std::vector<char> myCharVector;
myCharVector.push_back('a');
myCharVector.push_back('b');
myCharVector.push_back('c');
char *myCharPointer = &myCharVector[0];
So I was curious if it was possible to assign the address of the pointer in a similar way to this:
char *myPointer = "abc";
char **myDoublePointer = &myPointer;
I've tried:
char **myDoublePointer = (char**)&myCharVector;
But it doesn't work. Is there any way of achieving this?
You already know that &myCharVector[0] is a pointer to char. So if you store it in a variable:
char *cstr = &myCharVector[0];
then you can take the address of that variable:
char **ptrToCstr = &cstr;
But simply dereferencing twice like this:
char **ptrToCstr = &(&myCharVector[0])
is invalid because the value (&myCharVector[0]) isn't stored in memory anywhere yet.
In C++11, you can do:
char *myCharPointer = myCharVector.data();
But you cannot take the address of the return value of data() because it does not return a reference to the underlying storage, just the pointer value.
If the purpose is to be able to change what the pointer is pointing to, then you may really want a pointer to a vector, rather than a pointer to a pointer to a char. But, the STL doesn't let you change the underlying pointer within the vector itself without going through the regular vector APIs (like resize or swap).
You most definitely can't do this. std::vector and a char ** are completely different types of objects and you can't just "cast" one to another.
The reason you were able to do char *myCharPointer = &myCharVector[0] is that myCharVector[0] gives you a char, and thus &myCharVector[0] gives you the address of that char, which you can assign to a char *.
The only way you could convert a full std::vector into a char * (not char **) is to loop over your std::vector and construct a char * from the data manually.
For instance something like:
char *ptr = malloc(myCharVector.size()+1);
for (unsigned int i=0; i < myCharVector.size(); i++) {
ptr[i] = myCharVector[i];
}
ptr[myCharVector.size()] = 0;
Then ptr will be a C string of chars.

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.

Dynamic Structure in C++

struct testing
{
char lastname[20];
};
testing *pt = new testing;
pt->lastname = "McLove";
and I got
56 C:\Users\Daniel\Documents\Untitled2.cpp incompatible types in
assignment of 'const char[7]' to 'char[20]'
Why ?
Thanks in advance.
Because compile time arrays are constant. In your struct testing, you have an array of 20 chars, and you're trying to assign a pointer ("McLove", a compile time string, e.g., a const char*) to an array (a char[]), which won't work.
To copy the data "McLove" into the array, you need to use strncpy:
strncpy(pt->lastname, "McLove", 20); // 20 is the size of the array, change it when your array size changes, or better yet, use a constant for both
Or better yet, use std::string:
struct testing {
string lastname;
};
testing* pt = new testing;
pt->lastname = "McLove";
And now that will work, because std::string has an operator= that works with const char*.
As a side note, don't needlessly allocate objects on the free store (using new); allocate them on the stack:
testing pt; // not: testing* pt = new testing;
testing.lastname = "McLove"; // with std::string
The type of a string literal is pointer to const char. You can use that to initialize an array of char, but you can't assign to an array of char (from that or anything else).
Since you're apparently doing C++, you probably want:
struct testing {
std::string lastname;
};
testing pt;
pt.lastname = "McLove";
Allocating an object like testing dynamically is fairly unusual.
You can't assign one array to another. You're going to need to use strcpy (or better, strncpy).
Because string literals in C++ have the type const char[N] where N is the length of the literal, including the NULL character. So you're trying to assign a const char[7] to a array of type char[20], exactly what the compiler told you. Since arrays are not assignable this is invalid.
Use strcpy instead
strcpy( p-lastname, "McLove" );
Of course, you should also check if the destination is large enough to hold the source, or use some variant of strcpy that does this.