Си. Проблема с записью данных из файла в связанный кольцевой список
Всем привет! Изучаю си, и появилась задача из файла считать имена и записать их в кольцевой список. Имена читаются, но в список записывается последнее. Вот код:
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#define L 11
struct node
{
char* info;
struct node* next;
};
void prnlist(struct node* t)
{
if (t == NULL) //пустой список
return;
struct node* p = t->next;
while (p != t)
{
printf("%s ", p->info);
p = p->next;
}
printf("%s ", p->info);
printf("\n");
}
struct node* first(char* val)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
p->next = p;
p->info = val;
return p;
}
struct node* addtail(struct node* t, char* val)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
p->next = t->next;
t->next = p;
p->info = val;
return p;
}
struct node* read(const char* name)
{
FILE* fp;
struct node* t = NULL;
char buf[L], * temp;
if ((fp = fopen(name, "r")) == NULL)
return 0;
if ((temp = fgets(buf, L - 1, fp)) != NULL)
t = first(buf);
while (!feof(fp))
{
if ((temp = fgets(buf, L - 1, fp)) == NULL)
break;
t = addtail(t, buf);
//prnlist(t);
}
prnlist(t);
fclose(fp);
return t;
}
int main() {
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
struct node* names = read("Names.txt");
//prnlist(names);
}```
В файле names.txt
Ашот Иван Максим Алексей Александр
Но prnlist выводит только Александр Александр Александр Александр Александр
Ответы (1 шт):
Передавайте в addtail(t, strdup(buf)) (и в first() тоже).
Сейчас вы запоминаете адрес одной и той же памяти (в которую читаете файл) во всех элементах списка.
Кстати, addtail() можно чуть скорректировать и first() будет не нужен. Т.е. можно передать туда NULL (когда списка еще нет) и в зависимости от этого устанавливать next либо на начало списка, либо на только что созданный элемент (для первого в списке).
struct node* addtail(struct node* t, char* val)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
if (t) {
p->next = t->next;
t->next = p;
} else
p->next = p;
p->info = val;
return p;
}
При таком подходе read() (только ее надо обязательно переименовать) упроститься:
struct node* read_list (const char* name)
{
FILE* fp;
struct node* t = NULL;
char buf[L];
if ((fp = fopen(name, "r")) == NULL)
return 0;
while (fgets(buf, L - 1, fp))
t = addtail(t, strdup(buf));
prnlist(t);
fclose(fp);
return t;
}
Еще один момент. Ваш вариант prnlist() можно тоже сократить, например, так:
void prnlist (struct node* t)
{
if (t == NULL) {
struct node* p = t;
do {
printf("%s ", p->info);
p = p->next;
} while (p != t);
printf("\n");
}
}