#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 для примера кода.)