I am new to C and have never done anything with a non-OOP language.
I have an array of structs. It is global to the class and I parse a json with the results ending up in above mentioned array. I create an object (?) based on the struct that offers one property for every entry. After adding the items, the array turned out to have the same value on all of the positions.
I did remember C being tricky when it comes to values and pointers/references so I have made a little test to see whether the array actually only took the reference:
typedef struct {
char* name;
} ww_item ;
char nameW[40];
// iterating through json {
// strcpy(nameW, data);
ww_item w = { nameW };
ww_items [ position ] = w;
strcpy(nameW, "d"); //replaces the "Hello" with "d" in all previous ww_items
Obviously it does, which explains why my array ends up being a repetition of the last element that has been added to it instead of listing all the different strings I have added to it.
I am unable to find any short information on this and unfortunately my deadline is too close to read through a whole C book now. I'm pretty sure that my assumptions so far are true but now I do not know what to search for/ to look for in order to solve this problem.
I'm okay with an ugly solution or workaround but at the moment I am just stuck with this.
Thank you for your help.
Change the name member from a pointer to an array.
typedef struct {
char name[40];
} ww_item ;
and then use strcpy()
strcpy(ww_items[position].name, w);
There's no need for the w variable.
I have an assignment. I have the entire code but the snippet I am stuck on is the following.
The user must choose between the following projectiles.
Each projectile has a blast radius and this is the code I have so far (for this section):
userProjectileChoice = myProjectiles[3];
myProjectiles[0].projectileName = "cannonBall";
myProjectiles[0].blastRadius = 10;
myProjectiles[1].projectileName = "highExplosiveShell";
myProjectiles[1].blastRadius = 1;
myProjectiles[2].projectileName = "mortarBomb";
myProjectiles[2].blastRadius = 1000;
I need to use the struct as it is required.
Error message is: incompatible types when assigning to type int from type struct
The following has been included so you can see what the above code is referring to.
Projectile name has not been declared, am I declaring it in the above coding?
struct Projectile
{
char name[40];
float blastRadius;
};
float blastRadius;
double cannonBall = 0;
double highExplosiveShell = 1;
double mortarBomb = 2;
struct Projectile myProjectiles[3] = {{"cannonBall",0},{"highExplosiveShell", 1},{"mortarBomb", 2}};
Any assistance would be appreciated, but please keep it simple for me to understand as I said before I am new to this.
I'm not sure what type userProjectileChoice is, so I'm going to assume that it is the same type of the myProjectiles array. Try assigning each property one at a time as so:
userProjectileChoice.projectName = myProjectiles[3].projectileName
userProjectileChoice.blastRadius= myProjectiles[3].blastRadius
It's been years since I've programmed in C, but it's worth a shot.
Or perhaps you mean to assign the "index" and not the entire struct. Like I said, it's difficult to come up with a correct answer when I don't know the type of userProjectileChoice. Perhaps your problem is in the assignment at the beginning of the code. So if the 4th choice is selected then it should be as so:
userProjectileChoice = 3
I think my english is just to bad to understand the other articles about this. But anyway:
I just thought i could write a program (in C), that can store a set of cards.
Not complicated, just store values and names of cards and print them out.
I'm a beginner in C, and because i'm in the section "Strings in Structures" in my Book, i wanted to try out structures on my own. This is my Code so far:
#include <stdio.h>
struct card
{
int value;
char name[];
};
int main(void)
{
const struct card heart[13] = { {2,"two"}, {3,"three"}, {4,"four"}, {5,"five"}, {6,"six"}, {7,"seven"}, {8,"eight"}, {9,"nine"}, {10,"ten"}, {11,"jack"}, {12,"queen"}, {13,"king"}, {14,"ace"} };
int i;
for (i = 0; i < 13; ++i)
{
printf("The card heart-%s has the value of %i", heart[i].name, heart[i].value);
}
return 0;
}
I just wanted to test if it works, so i just wrote the heart-cards in the code. If i want to compile this file, my compiler (gcc/mingw) hits me with 26 errors. It says:
"(near initialization of heart[0])"
"non static initialization of a flexible array member"
I don't really understand this. In the book, everything works as expected. I tried to rebuild the code in the book and changing the names, but it doesn't work. I think it's a problem with the strings, because if i use integers only, everything works.
In already read in another post, that every string should be allocated manually, and there was a code example, but i don't know what all the lines should mean, and i want understand what my code does, so i don't copy + paste.
Could you explain me why this doesn't work?
PS: I am writing currently in windows, so please don't use bash commands to explain or something like that.
I am also german and my english is not the "yellow of the egg", try to explain without using complex 'sentence builds' (i hope you know what i mean :D) and unusual words.
Thanks for all help!
You need to create some space for the name of each card. Easiest way to do this would be to change your struct card definition to something like:
struct card
{
int value;
char name[16]; // doesn't have to be 16, but make sure it's large enough to hold each card name plus a '\0' terminator
};
The prior answers suggest allocating a fixed length for your names. This has limitations and even dangers. It is always a good idea to avoid it all together.
e.g. You want to alter the name during the game, e.g. "Ace (Trump Card)" but that might be both too long even worse overwrite memory. (Many of the known vulnarabilities in code are caused by buffer overruns)
You are also building in a limitation; What if your game needs translating into another language?
By using pointers, you don't need to resort to either variable length structures or fixed string lengths.
You also add the ability to add API access functions that set data, allowing checks before it's written, preventing buffer overruns.
Instead of using character array (aka strings) you should use pointers in your structures. If you follow the link at the bottom I take this further and use pointers to the structures themselves.
As the pointer storage size never changes your names can be of any length and even altered later, perhaps as the game progresses.
Your card could look something like
typedef struct card
{
int value;
char * name;
}
Now the initial assignment can be done like this
card_t card_ace = {14, "Ace"};
And the values are not fixed (unless that is what you want, then you make them const).
card_ace.value = 200;
card_ace.name = "Trump card";
or an array of cards like this
card_t suit_hearts[] = {{2,"two"}, {3,"three"}, {4,"four"}, {5,"five"}, {6,"six"}, {7,"seven"}, {8,"eight"}, {9,"nine"}, {10,"ten"}, {11,"jack"}, {12,"queen"}, {13,"king"}, {14,"ace"}}
Even better make the whole thing using pointers
typedef card_t * cards_t;
cards_t mysuit = &(card_t){2,"two"}, &(card_t){3,"three"}, ...
Perhaps consider makeing the suit a structure.
typedef struct
{
char * name;
card_t ** cards;
} suit_t;
typedef card_t * cards_t[];
suit_t mysuit = {
.name = "Hearts",
.cards = (cards_t){&(card_t){2,"two"}, &(card_t){3,"three"},....}
}
* For a fully working example of the latter, demonstrating using arrays of pointers to sidestep the limitations of variable length members of fixed arrays, see this gist on github
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
How do I dynamically create an array of struct in a function in C?
The struct:
typedef struct Track {
char artist[LONGSTR];
char file[LONGSTR];
int id;
int isAlbum;
char name[LONGSTR];
int pos;
char title[LONGSTR];
int time;
} Track;
The function:
int
processplaylist (struct Track** tracks, char* resp)
{
//count the tracks to return
//allocate space for the resulting tracks
*tracks = mem_alloc (count * sizeof (struct Track));
//process each track
return count;
}
And the usage:
char playliststr[] = "file: some-mp3\nTitle: Dire Straits - Romeo And Juliet\nName: TheRadio\nPos: 0\nId: 12\nOK\n"
struct Track* tracks = NULL;
int count = mpd_processplaylist(&tracks, playliststr);
Within the function the tracks are nicely processed and upto the return statement tracks points to the right location to get to the tracks. Most questions I have seen are about arrays to values, not structs.
This answer returns an array of structs, but I would like to return the count (question of style) and return the array through the parameter.
What is going wrong? After the function returns, count has the right value and tracks is still NULL.
As the not so nice people pointed out by down voting the question, the question is too broad and vague. I apologize for that, I was desperate.
As the nice people in the comments confirmed, the code is correct. Even though the debugger showed that just before the return statement everything was OK and after returning to the usage it was not.
By commenting out code lines and logging a lot, there are two things to note.
Within the function, you must refer to the individual tracks as (*tracks + i) or, for example, (*(*tracks + i)).file. Indeed, not shown in the sample code. I had tried *(tracks + i), &tracks[i] and tracks + i, which in the debugger all seemed to work and did not cause immediate errors. I guess the code messed up memory that only came out after the return.
Outside the function, in the usage, you refer to the tracks as an array, as tracks[i] or, for example, tracks[i].file.
I hope that at least my answer helps.
Firstly, I am really sorry if this has already been asked and resolved - I have spent ages searching and trying to adapt code samples to give me what I need... but sadly to no avail. Essentially I am just trying to copy the contents of one struct to another (which is documented here elsewhere but I cannot get it to work).
A scanner populates the following struct when it reads a barcode:
struct barcode
{
char *text;
int length;
int id;
int min;
int max;
};
This is instantiated as:
static struct barcode code = {0};
I instantiate another one of the same type:
struct barcode *barcodeHolder;
This is intended to store a copy of the scanned barcode. This is because other codes will then be scanned that indicated other steps such as barcodes to indicate numbers or stages (eg. end, start, etc). Once I want to write the struct contents to disk I use the "copy" of the struct as that is what I want.
However, the char *text property always equals 'c' and not the value of the barcode.
I copy them as follows:
barcodeHolder = malloc(sizeof(code));
barcodeHolder->text = malloc(strlen(code->text) + 1);
strcpy(barcodeHolder->text, code->text);
barcodeHolder->id = code->id;
barcodeHolder->length = code->length;
barcodeHolder->max = code->max;
barcodeHolder->min = code->min;
This is what I have got from other posts on a similar topic.
However, I am clearly doing something stupidly wrong and would welcome any help anyone might be able to offer so that my copy of the struct text element does actually get the right value copied.
Thank you!
Your code is not a pointer
You need this:
barcodeHolder = malloc(sizeof(code));
barcodeHolder->text = malloc(strlen(code.text) + 1);
strcpy(barcodeHolder->text, code.text);
barcodeHolder->id = code.id;
barcodeHolder->length = code.length;
barcodeHolder->max = code.max;
barcodeHolder->min = code.min;
I don't believe that your code is really:
static struct barcode code = {0};
[..]
strcpy(barcodeHolder->text, code->text);
Because the last statement would yield a compile error - because code is not a pointer you have to use code.text there (instead of code->text).
Assuming that you are actually using something like
struct barcode *code = ...;
You are allocating with your above code sizeof pointer of struct code bytes which is not enough for your structure.
Thus, copy it like this:
barcodeHolder = malloc(sizeof(struct barcode));
// alternative: ... = malloc(sizeof(*code));
*barcodeHolder = *code;
barcodeHolder->text = malloc(strlen(code->text) + 1);
strcpy(barcodeHolder->text, code->text);
Or, more simply:
barcodeHolder = malloc(sizeof(code));
*barcodeHolder = code;
barcodeHolder->text = strdup(code.text);
Probably unrelated, but if code in your example is a pointer to a struct, then your sizeof is wrong. It should be sizeof(*code) or sizeof(struct barcode). – Sean Bright 21 hours ago
#SeanBright In no way would I ever call myself a C programmer - ever! - so you saved completely here! Thank you. No, "code" is not a pointer in programme which confused me too... and was probably why I couldn't get anywhere. I just needed to get it work to prove we can do it for a demo. Should it progress I will come back (hopefully!) and revisit the code to better understand why it is working when it maybe shouldn't be. Thank you again!!!