Структуры в связанном списке

#c #struct #file-io #linked-list

#c #структура #file-io #связанный список

Вопрос:

Я все еще новичок в программировании на C, и у меня возникли некоторые проблемы. Я написал некоторый код для чтения файла, содержащего информацию об именах, возрасте, весе и росте людей. Каждая новая строка в файле представляет нового пользователя. Затем эта информация сохраняется в структуре, и эта структура затем добавляется в связанный список. По сути, я пытаюсь использовать этот связанный список как очередь, где каждый узел является структурой.

Вот как будет выглядеть файл, который я читаю: (формат — возраст, вес, рост, имя).

 20,60,170,Joe
23,70,175,Mike 
 

Моя проблема в том, что по какой-то причине каждый узел в связанном списке является одним и тем же, что является последней строкой текста файла. Так, например, каждый раз, когда я создаю структуру и добавляю ее в связанный список, у каждого узла будет имя «Майк», возраст «23» и так далее. Я поиграл с кодом и заметил, что проблем с чтением файла нет, а значения, присвоенные элементам структуры, верны (я распечатал значения для проверки). Однако, когда я просматриваю верхнюю часть связанного списка, затем удаляю из очереди (удаляю верхнюю часть), затем снова просматриваю верхнюю часть, значения всегда одинаковы. Так что я не уверен, в чем моя проблема.

Примечание: я написал общий код связанного списка, и с самим связанным списком проблем нет, поскольку я тщательно его протестировал.

Это мой код:

 #include <stdio.h>
#include "macros.h"
#include <string.h>

typedef struct
{
    int AGE;
    int WEIGHT;
    int HEIGHT;
    char NAME[51];
}Person;

int main()
{
    void* vdPtr;
    Person* topVal;
    Person person; 
    LinkedList* list = createLinkedList();
    char line[100];
    int i=0;
    int numPeople=0;
    FILE* fp;
    int age, weight, height;
    char name[51];
    fp = fopen("text.txt","r");
    
    while(fgets(line,100,fp) != NULL)/*reading file to see how many lines, and how many people*/
    {
        numPeople  ;
    }

    rewind(fp);

    while (i<numPeople)/*storing file data in the appropriate member for Person struct*/
    {
        fscanf(fp,"%d,%d,%d,%s",amp;age,amp;weight,amp;height,name);
        person.AGE = age;
        person.WEIGHT = weight;
        person.HEIGHT = height;
        strcpy(person.NAME,name);
        insertLast(list,amp;person);
        /*printing to see whether the values added to struct members are correct*/
        printf("%d %d %d %sn",person.AGE,person.WEIGHT,person.HEIGHT,person.NAME);
        i  ;
    }

    /*testing*/
    printf("nCount %d",getLinkedListCount(list));/*seeing how many nodes in the linkedList*/
    
    /*using void pointer to get the top value, then typecasting it to Person pointer*/
    vdPtr = viewTop(list);
    topVal = (Person*)(vdPtr); 
    
    /*viewing the top person*/
    printf("ntop is %s %d",topVal->NAME,topVal->AGE);
    
    /*deqeue*/
    removeTop(list);
    printf("nCount %d",getLinkedListCount(list));
    
    vdPtr = viewTop(list);
    topVal = (Person*)(vdPtr);
    printf("ntop is %s %d",topVal->NAME,topVal->AGE);
}
 

Кто-нибудь может сказать мне, где я ошибся и что делать, чтобы это исправить?

Комментарии:

1. Структуры в связанном списке являются ссылочными. т. Е. Один из членов (обычно последний) является указателем на саму структуру. Другие элементы можно рассматривать как полезную нагрузку или данные.

Ответ №1:

Вы постоянно добавляете один и тот же указатель в список. В каждой новой строке вы перезаписываете одну и ту же переменную. Итак, в итоге у вас есть один большой список указателей, указывающих на одно и то же. Вы должны создать новую структуру person для каждого пользователя следующим образом:

 #include <stdio.h>
#include "macros.h"
#include <string.h>

typedef struct
{
    int AGE;
    int WEIGHT;
    int HEIGHT;
    char NAME[51];
}Person;

int main()
{
    void* vdPtr;
    Person* topVal;


    LinkedList* list = createLinkedList();
    char line[100];
    int i=0;
    int numPeople=0;
    FILE* fp;
    int age, weight, height;
    char name[51];
    fp = fopen("text.txt","r");
    
    while(fgets(line,100,fp) != NULL)/*reading file to see how many lines, and how many people*/
    {
        numPeople  ;
    }

    rewind(fp);

    while (i<numPeople)/*storing file data in the appropriate member for Person struct*/
    {
        Person *person = (Person *)malloc(sizeof(Person)); //make new person object

        fscanf(fp,"%d,%d,%d,%s",amp;age,amp;weight,amp;height,name);
        person->AGE = age;
        person->WEIGHT = weight;
        person->HEIGHT = height;
        strcpy(person->NAME, name);
        insertLast(list, person);
        
        /*printing to see whether the values added to struct members are correct*/
        printf("%d %d %d %sn",person.AGE,person.WEIGHT,person.HEIGHT,person.NAME);
        i  ;
    }

    /*testing*/
    printf("nCount %d",getLinkedListCount(list));/*seeing how many nodes in the linkedList*/
    
    /*using void pointer to get the top value, then typecasting it to Person pointer*/
    vdPtr = viewTop(list);
    topVal = (Person*)(vdPtr); 
    
    /*viewing the top person*/
    printf("ntop is %s %d",topVal->NAME,topVal->AGE);
    
    /*deqeue*/
    removeTop(list);
    printf("nCount %d",getLinkedListCount(list));
    
    vdPtr = viewTop(list);
    topVal = (Person*)(vdPtr);
    printf("ntop is %s %d",topVal->NAME,topVal->AGE);
}
 

Я рекомендую прочитать о том, как работают указатели и управление памятью. Также имейте в виду, что этот код не освобождает выделяемую память, что вам все равно нужно сделать.

Ответ №2:

Не видя кода для insertLast(), тоже сложно ответить, но может случиться так, что вы создадите новую структуру для каждого пользователя, а затем передадите ее insertLast :

 Person* newPerson;
while (i<numPeople)/*storing file data in the appropriate member for Person struct*/
{
   newPerson = (Person *)malloc(sizeof(Person))
    fscanf(fp,"%d,%d,%d,%s",amp;age,amp;weight,amp;height,name);
    newPerson->AGE = age;
    newPerson->WEIGHT = weight;
    newPerson->HEIGHT = height;
    strcpy(newPerson.NAME,name);
    insertLast(list,newPerson);
    ...
 

Кажется, что список сохраняет только адрес данных, поэтому вам нужно создавать новые данные для каждого пользователя.

Ответ №3:

A struct , который должен использоваться в связанном списке, должен быть самоссылочным. т. Е. Один из членов (обычно последний) является указателем на саму структуру. Это то, что позволяет связывать сегменты данных вместе . (другие элементы можно рассматривать как полезную нагрузку или данные.) Например, ваша структура:

 typedef struct
{
    int AGE;
    int WEIGHT;
    int HEIGHT;
    char NAME[51];
}Person;
 

Могут быть реорганизованы, например, как:

 struct Person 
{
    int AGE;
    int WEIGHT;
    int HEIGHT;
    char NAME[51];
    struct Person *node;
};
 

Посмотрите на это простое начальное руководство по созданию и использованию связанных списков. (Перейдите на вкладку C для примера кода.)