Store char variables in other char variables in C - arrays

I am trying to do the following, create a multy-charr array with other char variables.
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
int size_line= sizeof(data_info_1)/sizeof(data_info_1[0]);
char data_info[3][size_line]={{data_info_1},{data_info_2},{data_info_3}};
One solution would be the following one, but I am not interested in just putting the string right in the data_info variable
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Could you please explain me why the first thing that I have writen is not valid. And if there is a solution to my problem.
Thanks.

To answer your question, neither of your solutions is correct, you can't initialize a 2D array of chars like that.
The second option would be valid if it wasn't a variable sized array, i.e.
char data_info[3][10]={"Wellcome", "Please" ,"If"};
^
Valid -> fixed size
Assignments like those would be possibe if you had an array of pointers:
char *data_info[] = {data_info_1, data_info_2, data_info_3}; //1
Or
const char *data_info[] = {"Wellcome", "Please", "If"}; //2
But these may not be what you need.
Option 1 will contain pointers to the original strings, any changes made to them through those pointers will be reflected in the original strings.
Option 2, the pointers are being initialized with string literals and those can't be changed, that's why I added the const qualifier as a metter of safety.
If neither of these constrains work for you, you'll need to copy the strings with something like strcpy, strncpy or better yet memcpy:
#include <string.h>
//...
memcpy(data_info[0], data_info_1, sizeof data_info_1);
memcpy(data_info[1], data_info_2, sizeof data_info_2);
memcpy(data_info[2], data_info_3, sizeof data_info_3);

Arrays may not be initialized by arrays. You may initialize a character array with string literals as you did in this declaration
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Relative to your case you could declare an array of pointers to char like for example
char * data_info[] = { data_info_1, data_info2, data_info3 };

Some remarks:
you do not need to divide by sizeof char becuse it is by definition 1
You can only use constant expressions when defining or initializing global variables char data_info[3][sizeof(data_info_1)];
To "store" one char array in other you need to copy it. Initialization will not work as you cannot assign the arrays.
#include <string.h>
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
char data_info[3][sizeof(data_info_1)];
void foo(void)
{
strcpy(data_info[0], data_info_1);
strcpy(data_info[1], data_info_2);
strcpy(data_info[2], data_info_3);
}
only structs or unions can be assigned. So you can wrap array into the struct and the assignment or initializations will copy the whole array.
struct stringWR
{
char str[50];
};
struct stringWR data_info_1 = {"Wellcome."};
struct stringWR data_info_2 = {"Please"};
struct stringWR data_info_3 = {"If"};
struct stringWR data_info[3];
void foo(void)
{
data_info[0] = data_info_1;
data_info[1] = data_info_1;
data_info[2] = data_info_1;
}
void bar(void)
{
struct stringWR data_info[3] = {data_info_1, data_info_2, data_info_2};
}

Related

Efficient way to re-assign char pointers to char arrays

I am dealing with char arrays and pointers to the arrays.
char firstAr[10] = "First";
char secondAr[10] = "Second";
char thirdAr[10] = "Third";
char* arPtrOne = firstAr;
char* arPtrTwo = secondAr;
char* arPtrThree = thirdAr;
I also have a second set of char arrays
char fourthAr[10] = "Fourth";
char fifthAr[10] = "Fifth";
char sixthAr[10] = "Sixth";
The above char arrays and char pointers can’t be altered (I have to work with them). I need to change the char arrays that my pointers point to, so that they now point to the second set of char arrays. I know I can do this by doing the following,
arPtrOne = fourthAr;
arPtrTwo = fifthAr;
arPtrThree = sixthAr;
This is fine for my example above but if I had 100 array I would need 100 statements to point them all to new char arrays. I am hoping someone could help me find a more efficient way to do this for my example above.
To stop any duplicate effort and also help others who have the same questions discover all the relevant information, This was also posted here https://forum.arduino.cc/index.php?topic=529860.0
How about using char**?
char* l_arry[100];
You can:
l_arry[0] = //your first string;
l_arry[1] = //your second string;
l_arry[2] = //your third string;
As I could not figure out how to point the existing pointers at the new char inside a loop I decided to fill the original arrays with the new char arrays contents. To do this I created all of the new char arrays inside an array char pointers so that I could reference them in a for loop. I then created a new array of char * and pointed them to the original arrays. I then used a strcpy inside a for loop to copy the contents of the new array to the original. This means that the original pointers remain unaltered and still point to the original arrays but now the arrays have updated contents. This has the same effect as pointing the pointers at new c arrays without having to actually do so.
char firstAr[10] = "First";
char secondAr[10] = "Second";
char thirdAr[10] = "Third";
char* arPtrOne = firstAr;
char* arPtrTwo = secondAr;
char* arPtrThree = thirdAr;
char *newStrings[3][10]=
{
"Fourth",
"Fifth",
"Sixth"
};
char *newPtrs[3]=
{
firstAr,
secondAr,
thirdAr
};
for(int i = 0; i<3;i++)
{
strcpy (newPtrs[i], newStrings[i]);
}

Error in initializing array in C

Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef int index_key;
typedef char text_t;
text_t *create_text()
{
//text_t text[SIZ];
text_t *c;
text_t text[]="fl";
c= text;
return c;
}
int main()
{
text_t * create();
return 0;
}
I get an error - expected expression before ‘]’ token. Why is this error occuring? Isn't text[] a global declaration and I can access it anywhere? What is wrong in this program and how should I correct it.
You cannot have an array definition like
text_t text[];
Either specify the size,
#define SIZ 256 //arbitary value
text_t text[SIZ];
or use initializer.
text_t text[] = {`A`, `B`, `C`};
EDIT:
As per the latest addition, please be informed that "sldk" (as you've iused) and {'s', 'd', 'l', 'k'} (as i've suggested) are not the same. The former is a string literal while the later being initalizer list of chars. You can use the second in your case, not the first one.
EDIT 2
That said, your create_text() function is wrong. Effectively, you're returning the address of a local variable text. Incorrect. Will invoke UB.
I see the following problems:
text_t text[];
is a declaration, not a definition. You have to add a line that defines text, such as:
text_t text[100];
The line
text[]="sldk";
is wrong on two accounts.
You cannot assign to an array using the = operator.
You cannot use text[] to access the array.
Here's a fixed version of your program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int index_key;
typedef char text_t;
// This is a forward declaration of the array.
text_t text[];
text_t *create()
{
text_t *c;
// One way to get some string into a char array.
strcpy(text,"sldk");
c = text;
return c;
}
// This is the definition of the array.
text_t text[100];
int main()
{
text_t * create();
return 0;
}
Update
Regarding your updated create_text function...
It should work since string literals are stored in read-only memory of the program. It will lead to problems as soon as you try to change anything in it. It's better to use a safer approach, such as:
text_t *create_text()
{
text_t *c = malloc(20);
strcpy(c, "fl");
return c;
}
The C language does not have a built in string data type unlike C++, Java or C#.
The strings are represented as arrays of characters in C. So any array in C should have some size.
int numbers[10];
char string[50];
The C function which operate on these types of strings ( like strlen which calculates the length of the strings expects a 'null' or '\0' character at the end of the array.
Initializing a character array with string literal like "test" will automatically insert a null character at the end.
char str[10] = "test";
characters stored {'t','e','s','t','\0'}
If you are initializing it with comma separated characters, you need to explicitly specify this character.
char str[10] = {'t','e','s','t', '\0'}; //explicit null character
So, generally the array size is one more than the maximum size of the string you want to store. So it is quite common to see declaration like the following.
char name[MAXLEN+1];
If you are using C++, you can use a build-in data type called string.
string str;
Hope this helps

String assignment in C

I'm new to C. The string assignment in the following code works:
#include<stdio.h>
int main(void){
char str[] = "string";
printf("%s\n",str);
}
But doesn't work in the following,even I give the index number to the name[]:
#include <stdio.h>
int main(void){
struct student {
char name[10];
int salary;
};
struct student a;
a.name[10] = "Markson";
a.salary = 100;
printf("the name is %s\n",a.name);
return 0;
}
Why does this happen?
You can't assign to an array. Two solutions: either copy the string:
strcpy(a.name, "Markson");
or use a const char pointer instead of an array and then you can simply assign it:
struct {
const char *name;
/* etc. */
};
a.name = "Markson";
Or use a non-const char pointer if you wish to modify the contents of "name" later:
struct {
char *name;
}
a.name = strdup("Markson");
(Don't forget to free the memory allocated by strdup() in this latter case!)
You cannot do this
a.name[10] = "Markson";
You need to strcpy the string "Markson" to a.name.
strcpy declaration:
char * strcpy ( char * destination, const char * source );
So, you need
strcpy( a.name, "Markson" );
char str[] = "string"; is a declaration, in which you're allowed to give the string an initial value.
name[10] identifies a single char within the string, so you can assign a single char to it, but not a string.
There's no simple assignment for C-style strings outside of the declaration. You need to use strcpy for that.
because in one case you assigning it in a declaration and in the other case you are not. If you want to do the equivalent write:
struct student a = {"Markson", 0};

Trouble with strings in C

I'm newbie in C world and I have two probably stupid questions.
I'm reading about structures in C and here is where I stuck. Let say we have structure like this
typedef structs {
char model[50];
int yearOfManufacture;
int price;
} Car;
Car Ford;
Ford.yearOfManufacture = 1997;
Ford.price = 3000;
//The line below gives me an error "Array type char[50] is not assignable
Ford.model = "Focus"
How to pass text into Ford.model in that case ?
My second question is also about strings.
This code works fine
char model[50] = "Focus";
printf("Model is %s", model);
But this one doesn't
char model[50];
model = "Focus";
Can anyone explain why it doesn't work ?
That's not how you copy strings in C. Try
strcpy(Ford.model, "Focus");
Alternatively (but with very different semantics):
typedef structs {
char const *model;
int yearOfManufacture;
int price;
} Car;
model = "Focus";
These C FAQs explain more about the issue:
Assign to array
How can an array be an lvalue, if you can't assign to it?
There are two ways to "put values in objects":
with initialization, when the object is created
with assignment, after the object is created
Though the syntax is similar, they represent different concepts.
You can initialize an array, but you cannot assign to it.
Also there's a special construct to initialize char arrays based on string literals
char arr[] = "foobar";
char arr[] = {'f', 'o', 'o', 'b', 'a', 'r', '\0'};
int arr[] = {1, 2, 3, 4};
// ...
but, assignement must be done element by element
char arr[4];
arr[0] = arr[1] = arr[2] = 'X';
arr[3] = '\0';
int arr[4];
arr[0] = arr[1] = arr[2] = 42;
arr[3] = -1;
A "special" way to assign elements of a char arrays one-by-one with a single statement is to use the library function strcpy() with prototype in <string.h>
#include <string.h>
int main(void) {
char arr[10];
strcpy(arr, "foo"); // same as arr[0]='f'; arr[1]=arr[2]='o'; arr[3]='\0';
return 0;
}
This (Ford.model = "Focus") is not possible. You have to copy the string into the array in the struct, best with strcpy:
strcpy(Ford.model, "Focus");
If your stdlib supports it, you should also consider an overflow safe version, e.g strncpy:
strncpy(Ford.model, "Focus", sizeof Ford.model);
At least I think its an extension function and not in the standard... I'm not sure.
You can't assign to a character array with =, you can only initialize it.
When you write
char model[50] = "Focus";
that is a initialization.
When you write
model = ...
that is an assignment. And, as I said, assignment to character arrays is not allowed.
You need to copy to the character array using strcpy(), e.g. strcpy(model, "Focus").
You can assign a string during definition, but anywhere else you have to use a different method, like the strcpy() function:
char model[50];
strcpy(model, "Focus");

string literal in c

Why is the following code illegal?
typedef struct{
char a[6];
} point;
int main()
{
point p;
p.a = "onetwo";
}
Does it have anything to do with the size of the literal? or is it just illegal to assign a string literal to a char array after it's declared?
It doesn't have anything to do with the size. You cannot assign a string literal to a char array after its been created - you can use it only at the time of definition.
When you do
char a[] = "something";
it creates an array of enough size (including the terminating null) and copies the string to the array. It is not a good practice to specify the array size when you initialize it with a string literal - you might not account for the null character.
When you do
char a[10];
a = "something";
you're trying to assign to the address of the array, which is illegal.
EDIT: as mentioned in other answers, you can do a strcpy/strncpy, but make sure that the array is initialized with the required length.
strcpy(p.a, "12345");//give space for the \0
You can never assign to arrays after they've been created; this is equally illegal:
int foo[4];
int bar[4];
foo = bar;
You need to use pointers, or assign to an index of the array; this is legal:
p.a[0] = 'o';
If you want to leave it an array in the struct, you can use a function like strcpy:
strncpy(p.a, "onetwo", 6);
(note that the char array needs to be big enough to hold the nul-terminator too, so you probably want to make it char a[7] and change the last argument to strncpy to 7)
Arrays are non modifiable lvalues. So you cannot assign to them. Left side of assignment operator must be an modifiable lvalue.
However you can initialize an array when it is defined.
For example :
char a[] = "Hello World" ;// this is legal
char a[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};//this is also legal
//but
char a[20];
a = "Hello World" ;// is illegal
However you can use strncpy(a, "Hello World",20);
As other answers have already pointed out, you can only initialise a character array with a string literal, you cannot assign a string literal to a character array. However, structs (even those that contain character arrays) are another kettle of fish.
I would not recommend doing this in an actual program, but this demonstrates that although arrays types cannot be assigned to, structs containing array types can be.
typedef struct
{
char value[100];
} string;
int main()
{
string a = {"hello"};
a = (string){"another string!"}; // overwrite value with a new string
puts(a.value);
string b = {"a NEW string"};
b = a; // override with the value of another "string" struct
puts(b.value); // prints "another string!" again
}
So, in your original example, the following code should compile fine:
typedef struct{
char a[6];
} point;
int main()
{
point p;
// note that only 5 characters + 1 for '\0' will fit in a char[6] array.
p = (point){"onetw"};
}
Note that in order to store the string "onetwo" in your array, it has to be of length [7] and not as written in the question. The extra character is for storing the '\0' terminator.
No strcpy or C99 compund literal is needed. The example in pure ANSI C:
typedef struct{
char a[6];
} point;
int main()
{
point p;
*(point*)p.a = *(point*)"onetwo";
fwrite(p.a,6,1,stdout);fflush(stdout);
return 0;
}

Resources