How to initialize struct char array? - c

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");

Related

Write to double const pointer

I want to implement my own string implementation for education. For that I defined a struct named string as follows:
struct string {
const char *const data;
const int length;
};
I use functions to create these string structs and then I assign them to variables.
In order to override the const int length I use the following trick:
*(int *) &result.length = // a int
Now I also want to write to the const char *const data.
As far as I know the first const makes sure that you cant edit the items at which the pointer points, and the second const is that you can't point the pointer to a different memory location. These are properties of an immutable string. So my question is: How can I assign something to the const char *const data like I did to the const int length?
Edit: result as shown above is an instance of the struct string
Form the struct string at its declaration and initialize it.
Also recommend to store the size and not the length and use size_t.
#include <stdio.h>
#include <stdlib.h>
struct string {
const char * const data;
const size_t size;
};
struct string string_copy(const char *src) {
size_t size = strlen(src) + 1;
char *copy = malloc(size);
if (copy) {
memcpy(copy, src, size);
} else {
size = 0;
}
struct string retval = {copy, size}; // ****
return retval;
// or return a compound literal (C99)
return (struct string){ copy, size};
}
void string_free(struct string s) {
free((void*)s.data);
}
int main(void) {
struct string a = string_copy("Hello");
printf("%zu <%s>\n", a.size, a.data);
string_free(a);
// do not use `a` subsequently
return 0;
}
I do not recommend to initialize with a string literal like struct string retval = {"World", 6}; as that limits the usefulness of struct string.
Using a opaque struct has many advantages #Jonathan Leffler that exceed this approach - mainly to keep other code from messing with the struct string.

How to return a multidimensional character array from a function in a header file in C

I have a main file, and a header file.
In main file, I want to return a 2D char array from a char function from header file. My char function is as following:
char character_distribution(int length, char redistribution[length][2])
{
char *buffer, distribution[256][2] = {0};
long lSize;
struct Bar result = funct();
buffer = result.x;
lSize = result.y;
length = collect_character_distribution(buffer, lSize, distribution);
reorganize_character_distribution(length, distribution, redistribution);
return redistribution;
}
And my main function is as follows:
#include <stdio.h>
#include "character_distribution.h"
void main()
{
int length;
char distribution[length][2];
distribution = character_distribution(length, distribution[length][2]);
int a;
for(a = 0; a < length; a++)
{
printf("%c\n", distribution[a][0]);
}
}
When I run my code, I get the following error:
warning: return makes integer from pointer without a cast
How can I fix the problem?
void character_distribution(int length, char redistribution[][2])
{
char *buffer, distribution[256][2] = {0};
long lSize;
struct Bar result = funct();
buffer = result.x;
lSize = result.y;
length = collect_character_distribution(buffer, lSize, distribution);
reorganize_character_distribution(length, distribution, redistribution);
}
int main()
{
int length = 2; //initialize
char distribution[length][2];
character_distribution(length, distribution);
int a;
for(a = 0; a < length; a++)
{
printf("%c\n", distribution[a][0]);
}
return 0;
}
If you really have to return the 2d array, one way (easy way) is to just put it in a struct
struct distribution_struct {
char x[256];
char y[2];
};
struct distribution_struct character_distribution(int length, char redistribution[][2]) {
struct distribution_struct dis;
//initialize the struct with values
//return the struct
}
And another way is to manually allocate memory for the 2d array in the function and return it
char** character_distribution(int length, char redistribution[][2]) {
//use malloc to create the array and a for loop to populate it
}
You cannot actually return an array from a C function. You can, however, return a pointer to such an array. The correct declaration in that case is:
char (*character_distribution(int length, char redistribution[][2]))[][2]
Sizing the initial dimension is not necessary and not, I suspect, actually conformant with standard C (at least, sizing it with length as you did in your question looks dubious to me). This is because arrays are passed by reference implicitly (and in this case, returned by reference explicitly) and it is not necessary to know the first dimension in order to calculate the address of an element having been given a pointer to the array (and the indices).
Note that you should not return a pointer to an array that is scoped locally to the function, since its storage is deallocated once the function returns (and such a pointer would then be invalid).
However, your question shows that you don't really need to return an array. Since arrays are passed by reference anyway, altering the passed-in array will causes changes that are also visible to the caller. Your code could be written as:
void character_distribution(int length, char redistribution[][2])
{
char *buffer, distribution[256][2] = {0};
long lSize;
struct Bar result = funct();
buffer = result.x;
lSize = result.y;
length = collect_character_distribution(buffer, lSize, distribution);
reorganize_character_distribution(length, distribution, redistribution);
}
And
#include <stdio.h>
#include "character_distribution.h"
void main()
{
int length = 256; // you need to initialise this...
char distribution[length][2];
// No assignment needed here!:
character_distribution(length, distribution /* [length][2] - remove this! */);
int a;
for(a = 0; a < length; a++)
{
printf("%c\n", distribution[a][0]);
}
}
(Of course this relies on the various other functions you call performing as they are supposed to).
Change the signature to this:
char** character_distribution(int length, char redistribution[length][2])
You are returning a multidimensional array, not a character.

Access structure variables in a loop

My requirement is that i create a structure with variables like
struct stu{
char var_01;
char var_02;
.
.
char var_30;
}stu_t;
and not use an array instead like
char var[30];
With the above requirement established, i can't figure how to access these variables in a loop by concatenating var_ + iterating integer. I know i cant just concatenate, store in a variable and use that variable to access.
Appreciate any help. Thanks!
Variable names have no meaning at run-time in a C program. The names are only for humans, they are removed during compilation. That's why you can't build variable names and somehow use those.
The solution is to use an external array with pointers:
stu_t my_stu;
char * vars[30];
vars[0] = &my_stu.var_01;
vars[1] = &my_stu.var_02;
/* ... and so on ... */
Then you can use vars to access into my_stu:
*vars[0] = 'u';
printf("var_01 is '%c'\n", my_stu.var_01);
Of course this isn't very pretty, but that's what you get.
You can use a pointer for that:
struct stu{
char var_01;
char var_02;
/* ... */
char var_30;
}stu_t;
char* ptr = &stu_t.var_01;
while(ptr <= &stu_t.var_30)
{
*ptr = '0';
printf("Character #%ld = %c \n", ptr - &stu_t.var_01, *ptr);
ptr++;
}
You can use union but it's rather "ugly" hack and I wouldn't recommend it, but if you really want it... (Still, it requires using arrays somewhere! Union will make structure and array use the same location in memory.) Example:
#include <stdio.h>
union Test
{
struct
{
char var_00;
char var_01;
char var_02;
char var_03;
char var_04;
};
char var[5];
};
int main()
{
union Test t;
t.var_01 = 'a';
printf("%c\n", t.var[1]);
return 0;
}
It outputs a.
Anyway, it's better to simply use array. Your requirement is kind of weird...
If your structure only contains chars, you can do this:
typedef struct stu_s {
char a;
char b;
char c;
} stu_t;
int main()
{
stu_t my_struct;
char *ptr = (char *)(&my_struct);
ptr[0] = 1;
ptr[1] = 2;
ptr[2] = 3;
printf("%hhd %hhd %hhd\n", my_struct.a, my_struct.b, my_struct.c);
}

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;
}

why char buf[] instead of char *buf in redis's sdahdr struct

In redis there is a struct called sdahdr:
struct sdahdr
{
int len;
int free;
char buf[];
}
Why not use char *buf instead, and why is sizeof(sdahdr) == 8 instead of 12?
The char buf[] is a placeholder for a string. Since the max length of the string is not known at compiletime, the struct reserves the name for it, so it can be properly adressed.
When memory is allocated at runtime, the allocation must include the length of the string plus the sizeof the struct, and then can pass around the structure with the string, accessible via the array.
char *s = "test";
struct sdahdr *p = malloc(sizeof(struct sdahdr)+strlen(s)+1);
strcpy(p->buf, s);

Resources