I'am writing a program where I need to add students to a array of structs.
Well, at the beginning I have the following struct array:
struct student *students[4];
After the declaration I add students like this to the array (just to have examples ...):
students[0] = malloc(sizeof(struct student));
students[0]->firstname = "Max";
students[0]->secondname = "Taler";
students[0]->number = 123456l;
...
Now I have to write a additional function, where I can pass the array as a parameter and add a new student.
So my function looks like this:
void add_student(struct student *students[],char *fristname, char *secondname, long number)
{
int i=0;
int new_position=0;
int return_value = 0;
// Search for the first available position for a new student
for(i=0; i<sizeof(students); i++)
{
if(students[i]==NULL)
{
new_position=i;
return_value = 1;
break;
}
}
struct student *new_student = malloc(sizeof(struct student));
students[new_position] = new_student;
students[new_position]->fristname = fristname;
students[new_position]->secondname = secondname;
students[new_position]->number = number;
return return_value;
}
I call the function with this code:
add_student(students, "Anni", "Karls", 123232);
But now my issue: In my "add_student" function I get an array that has a strange structur: it includes itself as the first element and every other element is shifted by 1 element.
Cant figure out what the problem is ... Can somebody please help?
EDIT: Somebody asked me, how this can be. How the array can include "itself" as the first element.
Well, here are screenshots of the debugger (xCode):
Before entering "add_student":
After entering "add_student" -> IN the function "add_student":
As you see, "students" has now 5 elements ...
Pass the length of the array to the function and change this
for(i=0; i<sizeof(students); i++)
to this
for(i=0; i<arrayLen; i++)
It seems you are inserting an element to some position in an array which has been allocated before hand; inserting is maybe more proper term than adding, but that is opinion.
You were applying sizeof operator on array type inside function - this will likely give you size of pointer in bytes because array name decays to pointer.
It's a little strange to statically allocate the array but then dynamically allocate the individual structures. You might consider dynamically allocating them all:
int num_students = 4;
struct student **students = malloc(sizeof(struct student) * num_students);
And then change your add_student function to look like this:
void add_student(struct student *students[], int arr_size, char *firstname, char *secondname, long number)
Related
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.
I'm just getting started with C, and having issues with struct. For instance I have:
struct student {
int id;
char name[25]
};
I want the user to add as many students as he needs:
int count = 0;
while (stop == 0){
struct student count
scanf("%d", count.id);
scanf("%s", count.name);
scanf("%d", stop);
}
It looks like I've to create struct student count (where count is a number) and keep creating these. So, I would like to create something like struct student 0, then struct student 1 and so on, so I can reference each student by it's count or number.
How would I get something like this to work?
This will automatically allocate memory when user requests it. It starts from a dimension of 1, up to virtually infinite (actually, up to the space available in RAM).
Of course if you want, you can change the initial size of size, as well as the growth rate of the array.
// Example program
#include <stdio.h> /* printf, scanf */
#include <stdlib.h> /* for realloc, malloc */
// Supposing student is defined like this:
struct student
{
int id;
char name[25];
};
int main()
{
int stop = 0;
int count = 0;
int size = 0;
// Using an array of students
size = 1;
struct student* students = malloc(size * sizeof(struct student));
while (stop == 0)
{
if(count >= size)
{
size ++;
students = realloc (students, size * sizeof(struct student));
if (students == NULL)
{
printf ("Failed to allocate more memory.\n");
return 0;
}
}
scanf("%d", &(students[count].id));
scanf(" %24[0-9a-zA-Z ]", &(students[count].name));
scanf("%d", &stop);
count = count + 1;
}
int i = 0;
for (i = 0; i < count; ++i)
printf("%d => %d %s\n", i, students[i].id, students[i].name);
}
I think you would like to create multiple instances of the struct in your first code sample for each user that is entered in the console, handled by the while-loop.
The easiest way to achieve this, is to use an array. I suggest you to first use an array with a fixed size, that means that you specify the array size in your code. This array will allow you to add as many student instances into it as the array size you've specified.
A simple example would be something like this:
// Define the student struct
struct student {
int id;
char name[25];
};
// ...
// Create an array with a fixed size to put the students in, and define a counter
struct student students[128];
int count = 0;
while(stop == 0){
// Create the struct to fill
struct student newStudent;
// Fill the struct with the user supplied data
scanf("%d", newStudent.id);
scanf("%s", newStudent.name);
scanf("%d", stop);
// Add the struct to the array, and increase the count afterwards
students[count++] = newStudent;
}
In the above example, I've added an array with a fixed size of 128, which you can change to whatever size you'd like. In the while-loop, an instance of a new struct is made, which is similar to before. This struct is being filled afterwards with data fed from the console. At the end of the while-loop the struct instance is added to the array of students. This will give you an array of all the students you've entered.
There is a downside to this solution however, and that's that in most cases, much more memory is consumed than is really used. This is because for the computer, it feels like 128 whole instances (or any other array size if specified) are stored in RAM, this can be quite expensive if only two instances will be really used. Also, like I said earlier, make sure to keep in mind that fixing the array size limits the amount of entries, this can also have a negative effect on your code. If you don't want to have these consequences, you may want to take a look at the solution described bellow.
You can make the size of the array dynamic, this is a little more advanced. If you'd like to achieve something like this, make sure to take a look at memory allocation functions, like Sourav Ghosh pointed out in a comment. You may also want to take a look at the code-example Michael made.
I hope this helps to solve the problem you're having. Happy coding!
I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}
i am a beginner so please cut me some slack on this one. So I have two functions and a struct in a header file I am currently working with.
This is the struct:
typedef struct ArrayList
{
// We will store an array of strings (i.e., an array of char arrays)
char **array;
// Size of list (i.e., number of elements that have been added to the array)
int size;
// Length of the array (i.e., the array's current maximum capacity)
int capacity;
} ArrayList;
Here is the first function, which creates and dynamically allocates memory for an array of strings. Capacity is the length of the internal array and size is the current size (how many strings are in the array which is essentially 0.)
ArrayList *createArrayList(int length){
char **array = NULL;
ArrayList *n;
int size = 0;
if (length > DEFAULT_INIT_LEN)
{
array = malloc(sizeof(int) * length);
n->capacity = length;
}
else
{
array = malloc(sizeof(int) * DEFAULT_INIT_LEN);
n->capacity = DEFAULT_INIT_LEN;
}
if (array == NULL)
panic("ERROR: out of memory in Mylist!\n");
n->size = size;
printf("-> Created new ArrayList of size %d\n", n->capacity);
return *array;
When I try to implement a pointer to the capacity member of the ArrayList struct inside another function within the same file, it is uninitialized instead of set as the value from the previous function. I.e. in createArrayList, n->capacity is equal to 10, but when used in printArrayList it is uninitialized and a random number appears such as 122843753.:
void printArrayList(ArrayList *list)
{
printf("\n%d", list->capacity);
return NULL;
}
My question is, how can I make it so all these functions "share" the same value when referring to the struct members. I.E. the first function prints -> Created new ArrayList of size 10, and the second function prints 10 as well. Also, I have to do this without changing the struct function itself. Sorry if this is a poorly worded question, but I can further clarify if it is confusing. Thanks in advance!
I see a couple of major issues with this code, in createArrayList you are returning array which is a char ** but you should be returning an ArrayList * which is what n is. So it looks like you want to assign array to n->array. The next issue is that n is an ArrayList * but you do not allocate memory for n.
I want to send a struct of symbol from one function to other functions, and i want to create an array that every cell will point to a different values of the following struct:
typedef struct symbol_def
{
char* sym_name;
char* sym_type;
unsigned short sym_address;
char sym_is_ext;
}symbol;
I'm trying to run this code:
//function-1
void compile_input_file(char* input)
{
symbol* curr_symbol;
//Intalize curr_symbol struct
curr_symbol = (symbol*)malloc(sizeof(symbol));
//memset((void)curr_symbol, 0, sizeof(symbol));
parse_command(line, &parser, curr_symbol, &index);
}
//function-2
void parse_command(char* line, parse_params* parser, symbol* curr_symbol, int* index)
{
sym = symbol_table_create(curr_symbol, "directive", sym_label, '0', index);
}
//function-3
symbol* symbol_table_create(symbol* curr_symbol,char* s_type, char* label, char is_ext, int* index)
{
int temp = *index;
curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol*)*(temp+1));
curr_symbol[temp].sym_type = s_type;
curr_symbol[temp].sym_name = label;
curr_symbol[temp].sym_address = 0;
curr_symbol[temp].sym_is_ext = is_ext;
temp++;
*index = temp;
return curr_symbol;
}
The problem is that the curr_symbol gets override all the time.
my purpose is to build a table of symbols, that in every iteration on the code i'll add another cell to the array
any ideas?
There is a problem, with the realloc It should be curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol)*(temp+1)); You were actually allocating it sizeof pointer which is 4 Bytes.
A Piece of Advice Realloc is a costly operation you should use it only if necessary and not on every instance
you could malloc in function3 instead of function1. If you do so you dont even need to pass the pointer via function2.
or else put a check to see if realloc is really necessary or not. Eg:- Check if the pointer is allocated memory. if(ptr!=null){ //realloc } This can work as a checking case too.
Best of Luck. :)