Array type 'char [n]' and 'uint8 [n]' is not assignable - c++

I'm trying to convert two types of values: char and uint8.
I have a function someFunction(TLabel *label, TEdit *edit). Inside of this function, I have a variable char var[6+1].
What I'm trying to do:
Get an Alphanumeric text (input of TEdit *edit), convert this text and put it inside of the var.
I know that if I call this function and put the *label and the *edit I can get whatever I want, but the problem is the conversion to associate the text of *edit in the var.
An example of my code (inside of the function):
char var[6+1];
label->Text = "Some text";
var = edit->Text;
//I will put var value inside of an another char (like a #define) that is in a struct, but doesn't matter for now
my_struct.valueOfVar = var;
And I have another function, it's the same code but the valueOfVar above is a uint8, and I can't convert it, too:
uint8 valueOfAnotherVar[6+1];

The issue is not with the types of the elements in the arrays, but rather that you simply can't assign one static array to another like this:
char a[7];
uint8 b[7];
a = b; // error
Instead, if you want to copy the values in the arrays, you can use std::copy like this:
std::copy(std::begin(b), std::end(b), std::begin(a));
If you have a dynamic array, you can still use std::copy, but you have to use the size of the array:
std::copy(b, b + N, a);
Make sure that both a and b point to at least N elements, otherwise you'll invoke undefined behavior.

The Text of a TLabel or TEdit is a System::String, which is an alias for System::AnsiString in C++Builder 2007 and earlier, and for System::UnicodeString in C++Builder 2009 and later. You did not say which version you are using, but it makes a big difference in your example.
You can't assign anything directly to a fixed array, like char[7] or uint8[7], by using operator= like you are attempting to do. You will need to instead convert and copy the String data into the allocated memory of the arrays, eg:
char var[6+1] = {};
label->Text = "Some text"; // OK - String has a constructor for 'const char*'
// if using CB2007 or earlier:
strncpy(var, edit->Text.c_str(), 6);
// if using CB2009 or later:
strncpy(var, AnsiString(edit->Text).c_str(), 6);
And then you can use one of these to copy the contents of var into valueOfVar:
memcpy(my_struct.valueOfVar, var, 7);
std::copy(var, var+7, my_struct.valueOfVar);
std::copy_n(var, 7, my_struct.valueOfVar);

Related

C++ Error: Cannot initialize an array element of type 'char' with an lvalue of type 'char [1024]'

First I convert my string to type char
//Convert string to char
string temp = "TFTFTFTFTFFFTTFFTTFFTTTTTTFFFF";
string temp = line;
char tab2[1024];
strcpy(tab2, temp.c_str());
cout << "The value of the string conversion is: " << tab2 <<endl;
Then I attempt to assign the tab2 contents to the char array:
char Array[] = {tab2};
Error: Cannot initialize an array element of type 'char' with an lvalue of type 'char [1024]
What happens in your case is that you are trying to initialize a c-style array with another c-style array.
C-style arrays can't be initialized in this manner nor can they be copied using a regular copy assignment.
To copy it using the copy assignment would require looping through and copying one element at a time and actually assigning a size to the second array.
There are two more practical approaches for your problem.
Either use std::array<> or another container type, instead of a char array, or use memcpy
For the former approach you'll just have to replace your arrays to type std::array<> and then you can initialize or copy with the regular copy assignment as you like.
For the latter approach you can use memcpy() to copy the memoryblock from the first c-style array to the other. Like this:
Read these reference pages on memcpy:
http://www.cplusplus.com/reference/cstring/memcpy
https://en.cppreference.com/w/cpp/string/byte/memcpy
{
/* ... */
char new_tab[1024] = {0};
std::memcpy(new_tab, prev_tab, sizeof(char)*1024);
std::cout << "The value after copy is: " << new_tab << std::endl;
/* ... */
}
Edit:
As your intent with this was not clear, but lets assume it is an assignment and you have to convert to an array and then copy the array to another array.
In that case read this for reference:
https://en.cppreference.com/w/cpp/string/byte/strncpy
http://www.cplusplus.com/reference/cstring/strncpy/
And then keep things as you had them but just change your char Array[] = {tab2};
To:
{
/* ... */
char new_tab[1024];
// Copies 1024 characters from prev_tab to new_tab
std::strncpy(new_tab, prev_tab, 1024);
/* ... */
}
Note: Also edited and added some reference links
You cannot do
char Array[] = {tab2};
because that expects expression tab2 to be bound to an element of array as per initialization list syntax. You cannot do
char Array[] = tab2;
either , because name of array tab2 decays to a pointer to its first element. Very same problem exists in C and it can be solved in same ways. Either copy them element by element, use memcpy or strcpy or C++ idiomatic std::copy, or use array as part on aggregate. But C++ got an aggregate you can use in <array>:
std::array<char,1024> tab2;
// we really have to check length there, you can overflow this buffer
strcpy(tab2.data(), temp.c_str());
auto Array = tab2;
A struct that allow a shallow copy will do too:
struct S {
char _data[1024];
char* data() { return _data; }
};
Shallow copy performed on S or on std::array copies storage of every element
of source to destination. This cannot be used with pointers because the pointer will be copied, not the storage it is pointing at.
That's essentially a model of std::array<char,1024> minus its bells and whistles.

C++ How to populate a static array of strings with new strings in different locations?

Say I got this
char* MapIds[5000] = { "Northeast Asia","Hanyang","Pusan","Pyongyang","Shanghai","Beijing","Hong Kong", /*...5000 values etc../* };
I tried
strcpy(MapIds[0], "gfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg");
But it crashes
How Do I keep changing them around without messing up the strings in other elements.
I dont want to use std::string or vector those cause crazy slow compile times.
Because you try to copy into a literal string ("Northeast Asia").
In C++ a literal string is really a constant array of characters, any attempt to modify such an array will lead to undefined behavior (which can sometimes express themselves as crashes).
If you want to make MapIds[0] point to a new string, then you simply use assignment:
MapIds[0] = "gfggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg";
Because literal strings are constant arrays of characters, C++ doesn't really allow you to have a char* to point to them, you must use const char*:
const char* MapIds[] = { ... };
However, a much better solution is to not use C-style strings and char pointers (const or not) at all, but only use std::string:
std::string MapIds[] = { ... };
Then you can modify the strings in the array itself, using plain assignment as shown above.

Convert auto (string) to char in D

For iterate with foreach loop and get dates over the files I need to have as input char [], but not string.
I wrote next code:
auto files = dirEntries ("E:\\ddd", SpanMode.shallow);
foreach (file; files)
{
char [] s = to!char[](file); //it's crap... and do not work...
writeln(file);
}
I use next method http://dlang.org/phobos/std_file.html#.getTimes
it's need as input char []: (in char[] name)
To get a mutable copy of immutable array you may use .dup:
char[] s = file.dup;
However in your case you don't need to do any conversion. getTimes accepts in char[] which is shortcut for scope const char[]. It it perfectly legal to pass immutable arrays as const arguments so it should "just work".
Your conversion line should look like:
... = to!(char[])(file.name);
This is because the shorthand template instantiation isn't valid for multiple tokens.
Second, there should be no need to convert to char[], as you said getTimes takes an "in char[]" which means it will not modify the string which means the immutable(char)[] can be passed without conversion.
You can also use :
const char[] s = cast(char[]) file;

Assigning a string of characters to a char array

I Want to know why the first statements works and why not second one in c++
char a[10]="iqbal"; // it works
a="iqbal"; // does not work
Strictly speaking, an array is not a pointer! And an array ( base address of the array ) cant be a modifiable lvalue. ie it cannot appear on the left hand side of an assignment operator.Arrays decay into pointers only in certain circumstances. Read this SO post to learn when arrays decay into pointers. Here is one more nice article which explains the differences between arrays and pointers
Also read about lvalues and rvalues here so that you get an idea of things which cannot appear on the LHS of =
char a[10]="iqbal";  // it works
In this case, internally what happens is
a[0] = 'i';
a[1] = 'q';
.
.
a[5] = '\0';
So everything is fine as array[i] is a modifiable lvalue.
a="iqbal"; // does not work
Internally, this is roughly equivalent to
0x60000(Address of a, but is a simple number here ) = Address of "iqbal"
This is wrong as we cannot assign something to a number.
The char array a will be static and can not be changed if you initialize it like this. Anyway you can never assign a character string a="iqbal" in c. You have to use strncpy or memcpy for that. Otherwise you will try to overwrite the pointer to the string, and that is not what you want.
So the correct code would do something like:
char a[10];
strncpy(a, "iqbal", sizeof(a) - 1);
a[sizeof(a) - 1] = 0;
The -1 is to reserve a byte for the terminating zero. Note, you will have to check for yourself if the string is null terminated or not. Bad api. There is a strlcpy() call that does this for you but it is not included in glibc.
The first line is not a statement but a declaration with an initialization.
The second line is an expression statement with the assignment operator.
You cannot assign arrays in C.
But you can initialize an array with the elements of a string literal.
why the first statements works and why not second one in c++
Because they are different statements, almost wholly unrelated. Do not be confused by the fact that they both use the = symbol. In one case, it represents object initialization. In the other case, the assignment operator.
Your first line is legal because it is legal to initialize aggregates, including character arrays.
Your second line is not legal because it is not legal to assign to an array.
Since this is C++, may I suggest that you avoid naked arrays? For character strings use std::string. For other arrays use std::vector. If you do, you example becomes:
std::string a = "iqbal"; // it works
a="iqbal"; // so does this
When writing
char a[10]="iqbal"
You are initializing the elements of the character array a with the characters. We can do the same with int type (note that the char type gets a slightly different treatment) :
int a[10]={1,2,...};
But writing the following after declaration part would be invalid as a would be treated just like a pointer. So writing something like
a={1,2,...};
or a="iqbal"
won't be making any sense!
try:
char a[10]="iqbal";
char *my_a = a;
and work with my_a.
In C++11 you can use a lambda to do the initialization, like so:
bool test = true;
/*const*/ char a[10] = { //Aggregate initialization
[=] //capture by value
()//no parameters
{ //start lambda
switch (test) {
case true: return *"test=true"; //*"xxx" don't return a pointer, but the 'string' itself
case false: return *"test=false";
} //switch
}()}; //}, close the lambda, (), call it, }; close aggregate initialization
This comes in handy when your environment does not support std::string, like NVidia's CUDA or some strange embedded environment.
The lambda gets to be inlined, so internally it translates to char a[10] = test?"xxx":"yyy";
If you have the option to do so, you obviously want to always use std::string, because fixed sized char buffers are fundamentally a bad idea.
If you use std::string you can convert that to a char array using: chararray = mystring.c_str();. Which is useful if you insist on using printf: printf("s = %s", mystring.c_str());.
You cannot assign a string literal to a char array after the latter's declaration.
A nice, simple & effective alternative is to use std::strcpy to do so, like so:
struct S
{
char name[30];
};
S s;
std::strcpy( s.name,
"The moribunds salute you." );

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.