如何使用文件中的 while 循环为我的结构赋值?

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

我有一个包含以下数据的文件:

Mike 234234
Jack 345345
Ben 456456
Willow 567567

我有如下结构:

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

我正在尝试遍历文件以使用上述结构格式创建节点,然后使用名为 add.

的函数将它们添加到双向链表中

这是 while 循环:

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);
}

然而,当我在控制台中显示链接列表时,它显示如下:

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

而不是以下内容:

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

我知道指针指向内存中的同一地址,并且该结构的所有实例都显示分配给这些内存地址的最终值。我的问题是,如何在内存中创建新地址并分别存储值而不是替换同一内存地址中的值?

这是我正在使用的完整代码,将其粘贴到 repl.it 中会产生相同的结果。

#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;
    }
  }
}

一种简单的方法是更改​​ makeNode 函数以使其分配 char 数组:

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;
}

但是不要忘记在释放节点之前释放它们...