Ошибка при работе с двусвязными списками

Рейтинг: 1Ответов: 1Опубликовано: 18.02.2023

Есть два двусвязных списка - в один данные просто записываются в конец, в другом записываются по порядку (т.е. сортируются по полю данных, в моем случае born). Обе эти операции выполняются парно, добавился в первый, добавился во второй. Однако возникает проблема - после второго записанного элемента ломается вывод.

Почему нельзя использовать temp в обоих функциях, она ведь не меняется? Если создать новую temp1 и через memcpy скопировать туда temp, а потом раскидать temp и temp1 по разным функциям, все заработает. На моменте добавления второго элемента переопределяется указатель на хвост и список лишается NULL в конце, или проблема в другом? Можно ли это избежать минуя memcpy?

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


typedef struct DataT{
    char name[16];
    char sex[16];
    char sport[16];
    int  growth;
    int  born;
}DataT;

typedef struct node{
    DataT* data;
    struct node* next, *prev;
}node;

typedef struct hwnd{
    node*  head, *tail;
}hwnd;

hwnd* CreateHwnd();    //создание дискриптора списка
node* CreateNode(node*);
node* FindNode(node*, DataT); //ищем конкретный
node* FindPlaceToInsert(node*, int);

void UnloadData(FILE*, hwnd*, hwnd*, hwnd*);
void UploadData(FILE*, node*);

void ClearMem(hwnd);  //удаление списка
void ShowNode(node*); //вывод узла
void ShowList(node*); //вывод списка

void* PopFront(hwnd*); //удалить первый
void* PopBack (hwnd*); //удалить последний
void* PopRandom(hwnd*, node*); //удалить произвольный

void* AddFront(hwnd*, node*); //добавить в начало
void* AddBack (hwnd*, node*); //добавить в конец
void* AddRandom(hwnd*, node*, node*); //вставить произвольно


int main(int agrc, char** argv)
{
    hwnd* Hwnd = CreateHwnd();
    hwnd* SortHwnd = CreateHwnd();
    hwnd* ChildHwnd = CreateHwnd();
    FILE* f = fopen("convest", "wb");
    fclose(f);
    char c;
    do
    {
        system("cls");
        puts("1 add\n2 show(N)");
        switch(c = getch())
        {
            case 0x31:  system("cls");
                        node* temp =(node*)malloc(sizeof(node));

                        temp = CreateNode(temp);
                        AddBack(Hwnd, temp);
                        AddRandom(SortHwnd, FindPlaceToInsert(SortHwnd->head, temp->data->born), temp);
                        break;
            case 0x32: system("cls"); ShowList(Hwnd->head); system("pause"); break;
            case 0x33: system("cls"); ShowList(SortHwnd->head); system("pause"); break;
        }
     }
     while(c != 27);
return 0;
}


node* CreateNode(node* temp){
    DataT* data = (DataT*)malloc(sizeof(DataT));
    printf("Name  : "); gets(data->name);
    printf("Sex   : "); gets(data->sex);
    printf("Sport : "); gets(data->sport);
    printf("Age   : "); scanf("%d", &data->born);
    printf("Growth: "); scanf("%d", &data->growth); getchar();
    temp->data = data;
    return temp;
}


node* FindPlaceToInsert(node* curr, int key){
    if(curr != NULL){
        while(curr->next && curr->data->born < key)
            curr = curr->next;
    }
    return curr;
}

void* AddFront(hwnd* hwnd, node* temp){
    temp->next = hwnd->head; //вставка в начало
    temp->prev = NULL;
    if(hwnd->tail)
        hwnd->head->prev = temp;
    else
        hwnd->tail = temp;
    hwnd->head = temp;
}


void* AddBack(hwnd* hwnd, node* temp){
    temp->prev = hwnd->tail; //вставка в конец
    temp->next = NULL;
    if (hwnd->tail)
        hwnd->tail->next = temp;
    else
        hwnd->head = temp;
    hwnd->tail = temp;
}


void* AddRandom(hwnd* hwnd, node* curr, node* temp){
    if(!curr)
        return AddBack(hwnd, temp);

    if(curr == hwnd->tail)//если место вставки хвост, смотрим вставить до или после
        if (curr->data->born < temp->data->born)
            return AddBack(hwnd, temp);

    if(curr == hwnd->head)
        return AddFront(hwnd, temp);

    temp->next = curr;
    temp->prev = curr->prev;
    temp->prev->next = temp;
    curr->prev = temp;
    return NULL;
}

void ShowList(node* head){
    int id = 0;
    system("cls");
    puts("| ID |      NAME       |   SEX   |   SPORT   | BORN | GROWTH |");
    while(head){
        printf("| %2d | %12s    | %7s | %7s   |%5d |  %4d  |\n", id++, head->data->name, head->data->sex, head->data->sport, head->data->born, head->data->growth);
        head = head->next;
    }
}

hwnd* CreateHwnd(){
    hwnd* temp = (hwnd*)malloc(sizeof(hwnd));
    temp->head = temp->tail = NULL;
    return temp;
}

Ответы

▲ 0

В общем, если в первом элемент просто добавлялся в конец и хранил NULL, то при вставке во второй, например, в середину, NULL заменялся на другой адрес и выводу приходил капут. Решение, которое помогло - создавать копию узла для второго списка через memcpy