got a question how to save a struct to an array and print it out in main().
My idea is, to get data of a .txt and then save it in a struct array. If i output it directly with printf() it works fine.
But if I want to save it in a struct array and print it out at themain() I get trash values, nothing or just the last read struct will be saved to all positions of the array.
My code looks like this:
typedef struct CAR {
char* nickname;
char* model;
} CAR;
void getInputFromFile(struct CAR *arr) {
. . .
. . .
char *nickname = malloc(...);
char *model = malloc(...);
int i=0;
while(fscanf(file,"%s %s\n", model, nickname)==2){
printf("%s %s\n", model, nickname); // this works fine!!!
// Now when i try to save it in a struct it doesn't work
arr[i]->model = model;
arr[i]->nickname = nickname;
i++;
}
free(nickname);
free(model);
}
int main (){
struct CAR* arr[size];
getInput(arr);
// Now iterate over arr to look at values
for(i = 0; i < size; i++){
...
}
}
File input format looks like this:
nickname model\n
nickname model\n
...
Thanks for all your help in advance!
you must duplicate (strdup) each string before to put it in your structure
arr[i]->model = strdup(model);
arr[i]->nickname = strdup(nickname);
currently all ar[]->model point to the same memory area, and that one was freed, same thing for all arr[]->nickname
in your program you forget also to allocate each CAR, so in fact :
arr[i] = (CAR *) malloc(sizeof(CAR));
arr[i]->model = strdup(model);
arr[i]->nickname = strdup(nickname);
Each struct needs allocated memory for the strings. Currently you have a single string buffer for nickname and model (so its being overwritten) and free it at the end of the loop, so now each struct is pointing to freed memory, not the original strings.
Related
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)
I have been trying to write a function with a pointer point to a struct array. After calling it my array should have a new struct element.
This is my function changed by ur guys suggestion
void addPic(pic *picture_Record, int picNumber){
pic tmp_Pic;
char tmp_fileName[100];
char tmp_description[100];
char tmp_location[100];
if (picture_Record[picNumber].description ==NULL || picture_Record[picNumber].fileName ==NULL||picture_Record[picNumber].location==NULL)
return;
printf("Enter: Picture Name, Picture Description, Picture Location, Picture People(int)\n");
scanf("%s%s%s%d",tmp_fileName, tmp_description, tmp_location, &picture_Record[picNumber].peopleCount);
tmp_Pic.fileName = (char*)malloc(strlen(tmp_fileName)+1);
tmp_Pic.description=(char*)malloc(strlen(tmp_description)+1);
tmp_Pic.location = (char*)malloc(strlen(tmp_location)+1);
strcpy(tmp_Pic.fileName, tmp_fileName);
strcpy(tmp_Pic.description, tmp_description);
strcpy(tmp_Pic.location, tmp_location);
picture_Record[picNumber] = tmp_Pic;
free(tmp_Pic.fileName);
free(tmp_Pic.description);
free(tmp_Pic.location);
printf("\nInput Done!\n");
This is how I call it.
int picNumber = 0
pic pictureRecord[Maximun_Picture +1]= { "" };
addPic(&pictureRecord[picNumber], picNumber);
picNumber++;
//testing
printf("%s",pictureRecord[0].location)
This is my struct.
typedef struct picture_Data
{
char* fileName;
char* description;
char* location;
int peopleCount;
}pic;
It doesnât work and printing me Null as th location of the first element. Why? Can somebody help me.
The problem is that this line
scanf("%s%s%s%d",pic_tmp.fileName, pic_tmp.description, pic_tmp.location, &pic_tmp.peopleCount);
assumes that pic.tmp has sufficient space allocated for fileName, description, and location. None of that is true, however, because all three fields remain uninitialized.
In order to fix this, change the code to read strings into a temporary buffer, and then copy it into dynamically allocated strings.
Here is how you do it for fileName; you need to do the same thing for all three:
char tmp_fileName[100];
char tmp_description[100];
char tmp_location[100];
scanf("%99s%99s%99s%d",tmp_fileName, tmp_description, tmp_location, &pic_tmp.peopleCount);
pic_tmp.fileName = malloc(strlen(tmp_fileName)+1);
strcpy(pic_tmp.fileName, tmp_fileName);
...
You can copy the struct with a single assignment, too:
picture_Record[picNumber] = pic_tmp;
Don't forget to call free on all three members of each struct to avoid memory leaks.
You should first have to allocate memory
void addPic(pic *picture_Record, int picNumber){
pic pic_tmp;
printf("Enter: Picture Name, Picture Description, Picture Location, Picture
People(int)\n");
pic_tmp.fileName = (char *)malloc(5);
picture_Record[picNumber].fileName = (char *)malloc(5);
scanf("%s%d",pic_tmp.fileName, &pic_tmp.peopleCount);
printf("\nInput Done!\n");
strcpy(picture_Record[picNumber].fileName, pic_tmp.fileName);
//picture_Record[picNumber].fileName = pic_tmp.fileName;
picture_Record[picNumber].description= pic_tmp.description;
picture_Record[picNumber].location = pic_tmp.location;
picture_Record[picNumber].peopleCount = pic_tmp.peopleCount;
printf("%s,%s",pic_tmp.fileName,picture_Record[picNumber].fileName );
}
I will read in two set of char* (or strings) using strtok, and since those two set of chars are related, (address : command\n) I decided to use a structure.
struct line* array = (struct line*)malloc(sizeof(file) * sizeof(struct line*));
This line mallocing space for the function gives me a segmentation fault and was wondering if you can tell me a proper way to malloc space for it. For context, here is the rest of my code:
struct line
{
char* addr;
char* inst;
};
while loop{
x = strtok(line,": ");
y = strtok(NULL,"\n");
strcpy(array[i].addr,x); //assume that x and y are always 3characters
strcpy(array[i].inst,++y);
i++;
}
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from #Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}
So I'm working on a little C program which is a little address book that automatically allocates memory when you add a new contact in it.
I'm using two typedef structures, the first one stores the info on the contact (name telephone etc.):
typedef struct
{
char nom[TAILLE1];
char tel[TAILLE2];
} CONTACT;
The seconde one contains a int with the number of contacts in the address book and an other one is the pointer to the other structure.
typedef struct
{
int nb;
CONTACT * contacts; // tableau
} LISTE_TABLEAU;
I created a function to import contact from a TXT file (first line the name of the person, second line their telephone number and so on). I simplified it with only the basic
int lireDonneesTxt(LISTE_TABLEAU* tab)
{
int i;
tab->contacts = (CONTACT *)malloc(sizeof(CONTACT)*13); (13 because there are 13 contact for testing purposes)
i = 0;
while( !feof(entree) )
{
fgets(ligne, TAILLE1, entree);
strcpy(tab->contacts[i].nom, ligne);
fgets(ligne, TAILLE1, entree);
strcpy(tab->contacts[i].tel, ligne);
i++
}
return 1;
}
When I compile my code there isn't any issue, no warning what so ever.
But when I run my code everything works great until I try and print a name on the screen, then the executable file crashes.
My main function looks something like this:
int main(void)
{
LISTE_TABLEAU *tabb;
tabb->nb = 0;
lireDonneesTxt(&tabb);
printf("%s", tabb->contacts[0].nom);
return 0;
}
If I add the same printf that is in the main at the end of my lireDonneesTxt function it prints the name without any problem.
I'm guessing that the data is not passed correctly to the structure.
I am now blocked and have no idea what to try to make this work !
Don't pass the address of the LISTE_TABLEAU pointer here:
lireDonneesTxt(&tabb);
just pass the pointer
lireDonneesTxt(tabb);
Also setting tabb->nb = 0; to unalocated memory is undefined behaviour.
The memory is not allocated for "tabb" & you are trying to access its member variable (tabb->nb) in main() function. It is illegal, thus the run time crash.
You can try the below code instead:
int main(void)
{
LISTE_TABLEAU tabb;
tabb.nb = 0;
lireDonneesTxt(&tabb);
printf("%s", tabb.contacts[0].nom);
return 0;
}
I'm trying to pass a pointer to an array of structs to a function. Then have the function create its own array of structures, populate it with data and then overwright the the old array with the new array.
I'm pretty sure the problem is with occurring when I try to overwrite the memory. I think that I could be either using the wrong method to overwrite the memory(should I be using the memory functions?) or I might be trying to overwrite the wrong thing. I'm not quite sure what I'm doing wrong. If someone could point me in the right direction I would be extremely thankful; I've been pulling the hair out of my head for like three hours now.
Struct:
typedef struct
{
char command;
int argc;
char* argv[];
}cmd;
Code:
int main(int argc, char *argv[])
{
[... irrelevant code]
cmd cmdv[count];
cmd* cmdv_ptr = &cmdv[0];
dissectCmd(cmdstr, cmdv_ptr);
printf("%i", cmdv[0].argc);
return 0;
}
void dissectCmd(char* str, cmd* cmdv)
{
[... irrelevant code]
cmd cmds[count];
int i = 0;
for(i = 0; i < count; i++)
{
cmd next;
next.command = 'u';
next.argc = 100;
cmds[i] = next;
}
cmdv = cmds;
}
You're not overwriting the memory -- the statement cmdv = cmds just copies the pointer (making cmdv point at cmds.) If you want to actually copy the memory, you need memcpy(cmdv, cmds, count * sizeof(cmd));
i'm not sure about this, but try declaring
void dissectCmd(char* str, cmd* cmdv)
as
void dissectCmd(char* str, cmd** cmdv)
changing
cmdv = cmds;
to
(*cmdv) = &cmds;
and changing current call from main which is now
dissectCmd(cmdstr, cmdv_ptr);
to
dissectCmd(cmdstr, &cmdv_ptr);
also, when you do this, you loose the address to the old array completely, creating a memory leak. unless you already free that memory in your second [... irrelevant code] passage :)