1

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!

John M
  • 37
  • 1
  • 4

2 Answers2

2

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);
bruno
  • 32,421
  • 7
  • 25
  • 37
  • Thank you very much for your detailed answer. Now it works. Helped me a lot! Oh, I see - I have to reserve the memory **extra for every element** of the struct? `strdup()` was the function I searched for...! Tried it several times with `strcpy()`! – John M Dec 18 '18 at 16:53
  • When you copy a pointer there is no duplication, when the pointed element have to be duplicated you must do it by yourself. The parameter type in _getInputFromFile_ is false, must be `getInputFromFile(struct CAR *arr[])` because _arr_ in a vector of pointers to CAR you need to allocate each CAR – bruno Dec 18 '18 at 16:59
  • _strcpy_ as _memcpy_ copy only, for the string you need both to allocate and copy, this is done by _strdup_ – bruno Dec 18 '18 at 17:02
  • is there another way to do this without strdup()? – John M Dec 19 '18 at 18:00
  • you can do the strdup by yourself through strlen + malloc + strcpy, but you cannot avoid to do the clone while you use `char *`. Of course you can replace the `char *` by a `char[]` and just do a strcpy into, but this is less practical because you have to know the longest possible string and you will use a long string even the value inside is small – bruno Dec 19 '18 at 18:05
  • thank you. If I replace the `char*` with `char[size]` do I have to allocate each CAR too like we did above? – John M Dec 19 '18 at 18:18
  • Yes of course CAR has to be allocated, but after `arr[i]->model = strdup(model);` is replaced by `strcpy(arr[i]->model, model);` and same for _nickname_ – bruno Dec 19 '18 at 18:27
  • But you don't have to choose between `char *` and `char[]` considering that point – bruno Dec 19 '18 at 18:31
  • hm, so it would be easier to implement the `strdup` as a own function at that point. Thanks for your advices! – John M Dec 19 '18 at 18:41
1

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.

lostbard
  • 5,065
  • 1
  • 15
  • 17