Initialize a structure with an array in a variable - c

How can we initialize a structure with an array (using its variable)?
This version works well:
MyStruct test = {"hello", 2009};
But this version is bugged:
char str[] = "hello";
MyStruct test = {str, 2009};

You cannot assign arrays in C, so unfortunately there's no way to do that directly. You may use strcpy to copy the data, though.
typedef struct {
char name[20];
int year;
} MyStruct;
int main() {
MyStruct a = { "hello", 2009 }; // works
char s[] = "hello";
MyStruct b = { "", 2009 }; // use dummy value
strcpy(b.name, s);
return 0;
}

The definition of MyStruct should contain a first member of type char const *.

Related

How to initialize struct char array?

I'm having trouble initializing a string of characters belonging to a struct. "Expression must have a modifiable lvalue". Do I need to use strcopy? I am not quite sure how to utilize this. Here is my code:
typedef struct {
char name[50];
int attackDamage;
int magicDamage;
int defense;
int power;
int type;
} ITEM;
int main() {
ITEM item[10];
char itemset[5][5] = { 0 };
char champion1[] = "Gnar";
char champion2[] = "Vi";
char champion3[] = "Fizz";
char champion4[] = "Draven";
char champion5[] = "Braum";
item[0].name = "Brutalizer"; // Having issues here
}
EDIT: I did this and seems there isn't anymore errors. Is this the proper way?
strcpy(item[0].name, "Brutalizer");
item[0].name is an array, you cannot assign a pointer (string literal) to an
array. You need to copy the contents, in this case with strcpy for example:
strcpy(item[0].name, "Brutalizer");
Or if the length of the source is not know beforehand, then you can use
strncpy to avoid buffer overflows:
strncpy(item[0].name, "Brutalizer", sizeof item[0].name);
item[0].name[sizeof(item[0].name) - 1] = '\0'; // make sure that it's \0-terminated
or you can use snprintf
snprintf(item[0].name, sizeof item[0].name, "Brutalizer");

populating struct fields in a separate function in C

getting empty values in the struct for this implementation since pointers are freed after call to myFunc ends. what's a good way of populating a struct when its fields are populated in a different function?
struct Poke {
char *name;
char *type;
};
void myFunc(struct Poke *p) {
char fish[5] = "fish";
char *name = fish;
char fillet[8] = "fillet";
char *type = fillet;
p->name = name;
p->type = type;
}
int main () {
struct Poke p;
myFunc(&p);
printf("%s\n", (&p)->name);
printf("%s\n", (&p)->type);
}
So you realize that the memory allocated for fish and fillet is deallocated when the function returns.
So you need memory that persists after the function call.
So you go and do some research and discover C's memory allocation functions like malloc and free. You will also need C's string handling functions like strcpy.
Go read about all the functions you can find in the include headers "stdlib.h" and "string.h".
One way is by allocating memory for the strings inside the structure itself, like this:
#include <stdio.h>
#include <string.h>
struct Poke
{
char name[64];
char type[64];
};
void myFunc(struct Poke *p)
{
char fish[5] = "fish";
char fillet[8] = "fillet";
strncpy(p->name, fish, 64);
strncpy(p->type, fillet, 64);
}
int main ()
{
struct Poke p;
myFunc(&p);
printf("%s\n", p.name);
printf("%s\n", p.type);
return 0;
}
You either need to make the strings static (static const for completeness) so they are persistent:
void myFunc(struct Poke *p)
{
static const char fish[5] = "fish";
char *name = fish;
static const char fillet[8] = "fillet";
char *type = fillet;
p->name = name;
p->type = type;
}
Or you need to define your structure members as char arrays and copy the string in:
struct Poke
{
char name[5];
char type[8];
};
void myFunc(struct Poke *p)
{
strcpy(p->name, "fish");
strcpy(p->type, "fillet");
}
The issue in this particular case is that char fish[5] = "fish"; creates a local variable and copies the string "fish" into it. So assigning char *name = fish; then p->name = name; stores the address of this local variable in your struct (and the same goes for p->type).
You can avoid this by directly storing the addresses of the string literals:
char *name = "fish";
char *type = "fillet";
And on a somewhat unrelated note, you don't need to dereference the address of p here:
printf("%s\n", (&p)->name);
printf("%s\n", (&p)->type);
The following is sufficient:
printf("%s\n", p.name);
printf("%s\n", p.type);

Malloc an array inside a struct

I'm trying to malloc an array inside a struct but I keep getting segmentation errors when I run the program.
The compares function is just something I'm testing so it shouldn't be a part of the problem
typedef struct {
char *string;
} prod_t;
int
main(int agrc, char **argv){
int i = 0;
prod_t *c = NULL;
char str2[100] = "abcd";
c->string = (char *) malloc( 5 * sizeof(char));
strcpy(c->string,str2);
compares(c->stock,str2,i);
return 0;
}
The problem is that you're allocating space for the string, but you're not allocating the struct at all. c remains set to NULL and you're trying to dereference it.
Allocate space for the struct before assigning to its members
prod_t *c = malloc(sizeof(prod_t));
And, as a sidenote for your next-to-fix error: this field doesn't exist
c->stock
You need to allocate space for the struct before you can assign to the string member:
prod_t *c = malloc(sizeof(prod_t));
Also see Do I cast the result of malloc?
First of all, don't cast result of malloc. You only need to do that in C++. In C, it can actually hide potential problems.
Second of all, you need to allocate (or statically declare) your structure.
Third, c->stock doesn't exist. You probably meant c->string.
typedef struct {
char *string;
} prod_t;
int
main(int agrc, char **argv) {
int i = 0;
prod_t *c = malloc( sizeof( prod_t ));
char str2[100] = "abcd";
c->string = malloc( 5 * sizeof(char));
strcpy(c->string,str2);
compares(c->string,str2,i);
return 0;
}

Incompatible types in assignment on struct

typedef struct s {
char name[20];
char last_name[20];
int height;
} s_t;
s_t my_s_t;
my_s_t.name = "John";
I get "Incompatible types in assignment" for the last line.
What am I doing wrong?
my_s_t.name = "John";
name is a char array. So you canĀ“t directly assign a string literal to it. You can use strcpy or similar function to copy the string literal OR declare name as char*.
Options:
1)
typedef struct s {
char name[20];
char last_name[20];
int height;
} s_t;
s_t my_s_t;
strcpy(my_s_t.name, "John");
2)
typedef struct s {
char *name;
char last_name[20];
int height;
} s_t;
s_t my_s_t;
my_s_t.name = "John";
You are trying to assign an array. Arrays are not assignable. This will fail for the same reason
char a[20];
a = "Hello"; /* Error */
In order to copy data into an array, you have to use a library function, like strcpy
strcpy(a, "Hello");
Meanwhile, it is possible to copy data into an array using core language features (instead of library functions) at the point of initialization, as in
char a[20] = "Hello";
In your case you can use aggregate initialization syntax to achieve the same
s_t my_s_t = { "John", "Smith", 2 };
As long as you are doing this at the point of initialization, it will work. If you have to do it later, then strcpy is your friend.

How to set a struct member of type string

I have a struct which contains a member called char *text. After I've created an object from the struct, then how do I set text to a string?
If your struct is like
struct phenom_struct {
char * text;
};
and you allocate it
struct phenom_struct * ps = malloc (sizeof (phenom_struct));
then after checking the value of ps is not NULL (zero), which means "failure", you can set text to a string like this:
ps->text = "This is a string";
typedef struct myStruct
{
char *text;
}*MyStruct;
int main()
{
int len = 50;
MyStruct s = (MyStruct)malloc(sizeof MyStruct);
s->text = (char*)malloc(len * sizeof char);
strcpy(s->text, "a string whose length is less than len");
}
Your struct member is not really a string, but a pointer. You can set the pointer to another string by
o.text = "Hello World";
But you must be careful, the string must live at least as long as the object. Using malloc as shown in the other answers is a possible way to do that. In many cases, it's more desirable to use a char array in the struct; i.e. instead of
struct foobar {
...
char *text;
}
use
struct foobar {
...
char text[MAXLEN];
}
which obviously requires you to know the maximum length of the string.
Example:
struct Foo {
char* text;
};
Foo f;
f.text = "something";
// or
f.text = strdup("something"); // create a copy
// use the f.text ...
free(f.text); // free the copy

Resources