MiniGunnR
MiniGunnR

Reputation: 5800

How to assign values to my structs with a while loop from a file?

I have a file with the following data:

Mike 234234
Jack 345345
Ben 456456
Willow 567567

I have a struct like the following:

typedef struct student {
  char *name;
  char *number;
  struct student *prev;
  struct student *next;
} Student;

I am trying to loop through the file to create nodes using the above struct format and then add them to a doubly linked list with a function called add.

Here is the while loop:

FILE *in = fopen("data.txt", "r");
char name[20];
char number[20];
while (fscanf(in, "%s %s", name, number) == 2) {
  list = add(list, name, number);
}

However when I display the linked list in the console it shows the following:

[Willow - 567567]
[Willow - 567567]
[Willow - 567567]
[Willow - 567567]

instead of the following:

[Ben - 456456]
[Jack - 345345]
[Mike - 234234]
[Willow - 567567]

I understand that the pointers are pointing to the same address in memory and all the instances of the struct are showing the final value assigned to those memory addresses. My question is, how do I create new addresses in memory and store the values separately rather than replacing the values in the same memory address?

Here is the entire code that I'm using, pasting it in repl.it will produce the same result.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student {
  char *name;
  char *number;
  struct student *prev;
  struct student *next;
} Student;

Student* makeNode(char *name, char *number);
void print(Student *list);
Student* add(Student *list, char *name, char *number);

int main(void) {
  FILE *in = fopen("data.txt", "r");
  Student *list;
  list = NULL;
  char name[20];
  char number[20];

  while (fscanf(in, "%s %s", name, number) == 2) {
    list = add(list, name, number);
  }

  list = add(list, "Mike", "234234");
  list = add(list, "Jack", "345345");
  list = add(list, "Ben", "456456");
  list = add(list, "Willow", "567567");

  print(list);
  return 0;
}

Student* add(Student *list, char *name, char *number) {
  Student* new = makeNode(name, number);

  if (list == NULL) {
    list = new;
  } else {
    Student *head = list;
    while (head->next != NULL) { // traverse to the end of the list
      if (strcmp(name, head->name) <= 0) { break; }
      head = head->next;
    }

    if (strcmp(name, head->name) <= 0) {
      // prepend
      if (head->prev != NULL) {
        new->prev = head->prev;
        new->next = head;
        head->prev->next = new;
        head->prev = new;
      } else {
        new->next = head;
        head->prev = new;
        list = new;
      }
    } else {
      if (head->next != NULL) {
        new->next = head->next;
        new->prev = head;
        head->next->prev = new;
        head->next = new;
      } else {
        new->prev = head;
        head->next = new;
      }
    }
  }

  return list;
}

Student* makeNode(char *name, char *number) {
  Student *node = (Student*) malloc(sizeof(Student));

  node->name = name;
  node->number = number;
  node->prev = NULL;
  node->next = NULL;

  return node;
}

void print(Student *list) {
  Student *current;

  if (list == NULL) {
    printf("List is empty.\n");
  } else {
    current = list;

    while (current != NULL) {
      printf("[%s - %s]\n", current->name, current->number);
      current = current->next;
    }
  }
}

Upvotes: 0

Views: 98

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148870

A simple way would be to change the makeNode function to make it allocate the char arrays:

Student* makeNode(char *name, char *number) {
  Student *node = (Student*) malloc(sizeof(Student));
  node->name = malloc(1 + strlen(name));
  node->number = malloc(1 + strlen(number));

  strcpy(node->name, name);
  strcpy(node->number, number);
  node->prev = NULL;
  node->next = NULL;

  return node;
}

But do not forget to free them before free-ing the Node...

Upvotes: 2

Related Questions