Hello everyone I got the following struct
struct Test
{
unsigned char* c_string;
unsigned int value;
};
I created a function that creates a new instance of this struct and initialize the attributes with random values like this
struct Test* createNewTest(){
struct Test *NewInstance = (Test * )malloc( sizeof(Test) );
NewInstance->value = rand();
Now I have to create a function that creates n completely initialized instances of my struct.
struct Test** createNewArray(unsigned int n){
};
Can anyone help me to do this? I dont really now how to start here
It's fairly straightforward. First, you'll need to allocate enough storage for n pointers to struct Test:
struct Test **array = malloc(n * sizeof *array);
if (!array) return array;
And then assign each pointer, using the function you have:
for (size_t i = 0; i < n; ++i)
array[i] = createNewTest();
Wrapping it all up, you get
struct Test **createNewArray(size_t n)
{
struct Test **array = malloc(n * sizeof *array);
if (!array) return array;
for (size_t i = 0; i < n; ++i)
array[i] = createNewTest();
return array;
}
Don't forget to write a matching free() function!
Also, consider whether you really want an array of pointers to Test - you may be better off with an array of Test objects instead.
I'm going to try to explain this without giving you the answer to your assignment verbatim ...
First, you need to allocate n times as much memory. malloc can allocate any amount, so you just need to calculate the number.
Second, you need to do the same initialization, but for each entry in the array. You'll need a loop for that.
Hint: in C, a pointer to a single instance and a pointer to a dynamic array are indistinguishable. ptr->value is the same as ptr[0].value, and ptr[1].value is the next element in the array.
Related
Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}
You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.
I have a function that sets values to a struct:
My struct:
struct entry {
char key[MAX_KEY];
int* values;
size_t length;
entry* next;
entry* prev;
};
My function:
// Sets entry values
void command_set(char **commands, int arg_num) {
struct entry e;
e.length++;
strcpy(e.key, commands[1]);
for (int i = 2; i < arg_num; i++) {
e.values[i - 2] = atoi(commands[i]);
}
}
where:
**commands: is a array of strings
arg_num: is how many strings are in the array
key: is the name of the entry
values: are integer values store in the entry
I run the code and I get a segmentation fault 11. I have narrowed it down to the line:
e.values[i -2] = atoi(commands[i]);
I assume that I have to use malloc to allocate memory as I don't appear to have gone out of bounds with my loop. I have tried to understand the correct way to allocate memory however I can't seem to get the syntax correct for allocating sizeof(int) to a dynamic array of integers.
I have tried:
e.values[i - 2] = malloc(sizeof(int));
and
e.values[i - 2] = (int) malloc(sizeof(int));
and
e.values[i - 2] = malloc(sizeof(int *));
However I get the error:
incompatible pointer to integer conversion assigning
to 'int' from 'void *' [-Werror,-Wint-conversion]
You must allocate the whole array:
e.values = malloc(sizeof(int) * (arg_num - 2))
Important: Remember to call free when you're done with the memory or you will have a memory leak.
You have another problem though, unrelated to the one you're asking about.
You do
struct entry e;
e.length++;
When the structure object e is defined, it is uninitialized, all its members will have an indeterminate value. Using such uninitialized data in any way except to initialize it will lead to undefined behavior. And you do use such uninitialized values when you do e.length++.
That increase simply doesn't make any sense in the code as you show it. On the other hand, that function doesn't make a lot of sense anyway since the variable e and all its data will simply "disappear" when the function returns. So I can only assume that it's not the complete function you show us.
To initialize the structure to all zeroes, simply do
struct entry e = { 0 };
as your struct is as follows
struct entry {
char key[MAX_KEY];
int* values;
size_t length;
entry* next;
entry* prev;
};
then you should allocate memory to it as
e.values =(int *)malloc(arg_num*sizeof(int));
like if you have 10 values then you are allocating 10*4 values to it.
and invoke free on it
free(e.values)
when the e or e.values is no more useful. for more information you can see here
Modify the function as below.
void command_set(char **commands, int arg_num) {
struct entry e;
e.length++;
strcpy(e.key, commands[1]);
//here is the memory allocation
e.values = malloc(arg_num-1 * sizeof(int));
for (int i = 0; i < arg_num-1; i++) {
e.values[i] = atoi(commands[i+1]);
}
}
I'm currently working on dynamically allocating my array of structures and I'm unsure how to continue. This is my structure:
struct Word_setup
{
char word[M];
int count;
} phrase[N];
I know malloc returns a pointer to a block of memory, but I'm not sure how this works when it comes to an array of structures.
If anyone could please clarify that would be much appreciated!
Probably you meant:
struct Word_setup {
char word[M];
int count;
};
It's a good idea to avoid defining variables in the same line as a struct definition anyway, to help with code readability.
Then you can allocate an array of these:
int main()
{
struct Word_setup *phrase = malloc(N * sizeof *phrase);
// use phrases[x] where 0 <= x < N
phrase = realloc(phrase, (N+5) * sizeof *phrase);
// now can go up to phrases[N+4]
free(phrase);
}
Of course you should check for failure and abort the program if malloc or realloc returns NULL.
If you also want to dynamically allocate each string inside the word then there are a few options; the simplest one to understand is to change char word[M] to char *word; and each time you allocate a phrase, write the_phrase.word = malloc(some_number); . If you allocate an array of words you'll need to loop through doing that for each word.
I suppose that N and M is a compile-time known constants. Then just use sizeof, .e.g.
struct Word_setup*ptr = malloc(sizeof(struct Word_setup)*N);
Maybe you want a flexible array member. Then, it should always be the last member of your struct, e.g.
struct Word_setup {
int count;
unsigned size;
char word[]; // of size+1 dimension
};
Of course it is meaningless to have an array of flexibly sized structures -you need an array of pointers to them.
I made a structure like so:
struct ponto {
int x;
int y;
int z;
};
1) Can I initialize the int's with a default value? int var = value; doesn't seem to work, compiler says "syntax error before '=' token" or something of sorts.
2) I need to work with several of these like in a array of structures, but I only know how many I need after the application starts up, after reading a file. How can I malloc this?
Thanks in advance
EDIT: So many answers, I'm grateful. Sadly I can only mark one
a) You can initalise with
struct pronto p = {1,2,3};
In recent compilers (not sure how portable this is, think it's C99?)
b) You can allocate an array with malloc:
struct pronto *array = malloc(sizeof(struct pronto) * NUMBER);
To initialize your structure members to 0, do:
struct ponto foo = { 0 };
To malloc() an array of the right size, do:
struct ponto *arr = (struct ponto *) malloc(COUNT * sizeof(struct ponto));
Don't forget to free() the array when you're done with it.
struct ponto* create_and_init_ponto(int n)
{
struct ponto* array;
int i;
array = (struct ponto*)malloc( n * sizeof(struct ponto) );
for ( i = 0; i < n; ++i )
{
array[ i ].x = 0;
array[ i ].y = 0;
array[ i ].z = 0;
}
return array;
}
You'e made a structure definition, now you have to create a variable of that structure before you can set the fields:
struct ponto xyz;
xyz.x = 7;
To allocate enough space:
int need_to_have = 24;
struct ponto *pontos = malloc (need_to_have * sizeof(struct ponto));
You cannot have "default" values for structure members. Space is not allocated for a structure definition. You're just creating a new type (like the inbuilt int). When you actually define a variable of type ponto, space will be allocated to it.
You can make an educated guess about how many you will need, allocate space for that many (using malloc) and go ahead. If you find that you're reaching the limit, you can use the realloc function to resize your array.
1) You cannot give a specific structure default values for its elements at the language level, because all variables in C are uninitialized unless you explicitly initialize them (or make them static/external in which case they're zero-initialized). If you design your structs such that all-zeros is a good set of initial values, though, you can always initialize like this:
struct foo myfoo = {0};
The {0} serves as a universal zero-initializer which works for any type.
If you need different defaults, the best way is to use a macro and document that code using your structure must use the macro:
#define FOO_INITIALIZER { 1, 2, 3 }
struct foo myfoo = FOO_INITIALIZER;
2) If you know before you start using any of the struct how many you will need, simply malloc them all once you know the number:
if (count > SIZE_MAX / sizeof *bar) abort();
struct foo *bar = malloc(count * sizeof *bar);
Note the proper idiom for calling malloc and avoiding overflow vulnerabilities.
If you don't know the number you'll need until you start working with them, start out by allocating a decent number, and if you run out, increase the number by a fixed multiple, for example doubling the size is common and easy. You'll want to check for overflows here. Then use realloc.
Question #1: If you need to initialize int with a value:
struct ponto p1;
p1.x = p1.y = p1.z = 3; // initializing with three
Alternatively, if you want to initialize all values to 0, you can use memset like this:
memset(&p1, 0, sizeof(struct ponto));
Question #2: To use malloc:
struct ponto *ps;
ps = (struct ponto *)malloc(N*sizeof(struct ponto));
// where N is your element count.
This will allocate memory to store N elements of type struct ponto. After that, you can initialize its values with:
int initvalue = 3; // assuming you want to initialize points with value 3
for (i=0; i<N; i++) {
ps[i].x = ps[i].y = ps[i].z = initvalue;
}
I'm trying to create an array of structs and also a pointer to that array. I don't know how large the array is going to be, so it should be dynamic. My struct would look something like this:
typedef struct _stats_t
{
int hours[24]; int numPostsInHour;
int days[7]; int numPostsInDay;
int weeks[20]; int numPostsInWeek;
int totNumLinesInPosts;
int numPostsAnalyzed;
} stats_t;
... and I need to have multiple of these structs for each file (unknown amount) that I will analyze. I'm not sure how to do this. I don't like the following approach because of the limit of the size of the array:
# define MAX 10
typedef struct _stats_t
{
int hours[24]; int numPostsInHour;
int days[7]; int numPostsInDay;
int weeks[20]; int numPostsInWeek;
int totNumLinesInPosts;
int numPostsAnalyzed;
} stats_t[MAX];
So how would I create this array? Also, would a pointer to this array would look something this?
stats_t stats[];
stats_t *statsPtr = &stats[0];
This is how it is usually done:
size_t n = <number of elements needed>
stats_t *ptr = malloc (n * sizeof (stats_t));
Then, to fill it in,
for (size_t j = 0; j < n; ++j)
{
ptr [j] .hours = whatever
ptr [j] .days = whatever
...
}
The second option of a pointer is good.
If you want to allocate things dynamically, then try:
stats_t* theStatsPointer = (stats_t*) malloc( MAX * sizeof(stats_t) );
as Roland suggests.
Just don't forget to
free(theStatsPointer);
when you're done.
Use malloc():
http://en.wikipedia.org/wiki/Malloc
malloc is your friend here.
stats_t stats[] = (stats_t*)malloc(N * sizeof(stats_t));
stats sort of is a pointer to the array. Or you can use stats[3] syntax as if it were declared explicitly as an array.
Based on your replies to other answers it looks like you need a dynamic data structure like a linked list. Take a look at the queue(3) set of facilities.