Создание подлиста из связанного списка на основе позиции?

Я пытаюсь ввести функцию, которая принимает 2 связанных списка. Один имеет значения для печати, а второй имеет позиции для связанных значений списка для печати. Это дает мне ошибку, которую я помещаю в качестве комментария в коде.

Структуры

typedef int Item;
typedef struct node_struct * link;
typedef struct list_struct * list;

struct node_struct {
    Item item;
    link next;
};

struct list_struct {
    link first;
    int length;    
};

Функция:

list sublist(list A, list pos_list) {
    link tempOne;
    link tempTwo;
    link node = malloc(sizeof *node);
    tempOne = pos_list->first;
    tempTwo = A->first;
    int counter;
    while(tempOne->next != NULL)
    {
        counter = 0;
        while(counter < tempOne->item && tempOne->next != NULL)
        {
            tempTwo = tempTwo->next;
            counter = counter+1;
        }
        node->item = tempTwo->item; //EXC_BAD_ACCESS code:1
        node = node->next;
        tempTwo = A->first;
        tempOne = tempOne->next;
        counter = 0;
    }
    return node;

1 ответ

  1. Есть куча плохих практик в коде, которые делают понимание (и, следовательно, отладку и поддержание) такого кода очень трудным для вас и для нас.

    • Вы создаете typdef указателя, когда нет намерения скрывать фактические данные за указателем
    • Вы создаете связанный список позиций и связанный список данных, используя один и тот же тип данных. Я понимаю, что в вашем случае оба int, но тогда не используйте вводящее в заблуждение typedef int Itemи просто придерживайтесь использования int
    • tempOne иtempTwo, вероятно, худшие варианты именования в этом случае не только для вызова переменных с неинтуитивными именами , такими какtemp, но и для вызова первого arg как Twoи второго arg какOne-как контринтуитивный, как он может получить
    • Я могу видеть случаи, когда вы используете 2 различные структуры node_struct(которые, честно говоря, я бы назвал node) и list_structвидите node_structкомментарий), но в этом примере вам не нужноlist_struct, это только добавляет больше путаницы в код.
    • Работу «найти» (внутреннюю )действительно следует for loopвыполнять в отдельной функции, чтобы можно было легко обрабатывать ошибки, а не путать внутреннюю петлю с внешней

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

    после того, как вы это сделать node = node->next;вам нужно mallocэто снова. Или, скорее, просто malloc его перед использованием его на линии node->item = tempTwo->item;и избавиться от mallocвнешней стороны петли

    У меня нет компилятора c под рукой, поэтому я не мог его проверить. Но я не вижу никаких других проблем

    РЕДАКТИРОВАТЬ

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

    Ниже приведен способ написания этого кода. Помните, что это не отлаженный и протестированный код, а просто выражение идеи (первый черновик, если хотите)

    typedef struct Node_ Node;
    
    struct Node_ {
        int Item;
        Node* Next;
    };
    
    Node* GetNodeAt(Node *dataList, int indx) {
        for (int i = 0; i < indx && dataList != NULL; ++i)
            dataList = dataList->Next;
        return dataList;
    }
    
    Node* SubList(Node *dataList, Node *posList) {
        Node* origDataList = dataList;
    
        Node *currentRetNode = malloc(sizeof(Node));
        Node *prevRetNode = NULL, *returnList = currentRetNode;
    
        while (posList->Next != NULL) {
            // Find the node in dataList
            Node *node = GetNodeAt(dataList, posList->Item);
    
            // create/manage the linked list to be returned
            prevRetNode = currentRetNode;
            currentRetNode->Next = malloc(sizeof(Node));
            currentRetNode->Item = node->Item;
            currentRetNode = currentRetNode->Next;
    
            posList = posList->Next; // move to the next index
        }
    
        free(currentRetNode);
    
        if (prevRetNode == NULL)
            returnList = NULL;
        else
            prevRetNode->Next = NULL;
    
        return returnList;
    }