Не выдает значения запрашиваемого списка

я делаю программу, которая создает 2 списка, заполняет 1 список рандомными числами, а потом ссылается на второй пустой список и проверяет его на наличие в нем чисел из первого. То есть, заполняет его числами по одному разу, например, имеется список l1 = 4 4 3 3 2 2 4, следовательно, во второй списке должны быть l2 = 4 3 2. Но при выполнении программы, в функции search пишет, что происходит разыменовывание пустого указателя l3. Подскажите пожалуйста, как это исправить

#include <time.h>
using namespace std;

struct list {
    int data;
    list* next;
};
list* head;
void createlist(int n, list** head) {//создает список
    if (n>0)
    {
        (*head) = new list();
        (*head)->data=rand()%10;
        (*head)->next = NULL;
        createlist(n - 1, &((*head)->next));
    }
}
void print(list* head) {//выводит список
    cout << "Список имеет значения: ";
    while (head != 0) {
        cout << head->data << " ";
        head = head->next;
    }
    cout << endl;
}

void search(list*l1, list*l2) {
    int i=0, j=0;
    while (l1 != NULL) {
        j=l1->data;
        if (l2==0){
            l2->data = j;
            l2->next = NULL;
        }
        else while (l2 != 0 && i!=1) {
            if (j==l2->data){
                i = 1;
            }
            else {
                l2->data = j;
                l2->next = NULL;
                i = 1;
            }
        }
    }
}

int main() {    
    setlocale(0, "RUS");
    srand(time(0));
    int n;
    cout << "Введите количество элементов списка ";
    cin >> n;
    list* l1;
    createlist(n, &l1);// создает первый список
    print(l1);// выводит первый список

    list* l2 = new list;
    search(l1, l2);
    print(l2);// выводит результирующий список
}

Ответы (1 шт):

Автор решения: Павел Ериков

Вместо того, чтобы писать где у вас ошибки, я просто прокомментирую ваш код. В комментарии где стоит ! стоит обратить внимание:

void search(list*l1, list*l2) {
    int i=0, j=0;
    //Цикл который проходит по первому списку
    while (l1 != NULL) {
        j=l1->data;
        //Если l2 - нулевой указатель
        if (l2==0){
            //! Записываем l2 поле data и next
            //А как мы это делаем? У нас l2 - нулевой указатель
            l2->data = j;
            l2->next = NULL;
        }
        //Иначе проходим по второму списку и пока i != 1
        else while (l2 != 0 && i!=1) {
            //! Если в списке 2 уже есть элемент со значением
            //j, то i = 1
            //Хорошо вы нашли одинаковый элемент. Просто перейдите
            //к следующему элементу в l1
            if (j==l2->data){
                i = 1;
            }
            //! Иначе присваиваем l2 data = j и next = NULL и i = 1
            // 1*
            //И так же устанавливаем i = 1
            //То есть после первой итерации у вас i = 1 и цикл остановится
            //То есть вы максимум прошли 1 элемент из списка l2
            else {
                l2->data = j;
                l2->next = NULL;
                i = 1;
            }
        }
        //Хорошо, а что дальше? l1 равен не NULL, и что вы делаете дальше?
        //Может стоит перейти к следующему элементу l1?
    }
}

Немного расскажу про 1*:

Если j != l2.data, то вы наверно пытались добавить новый элемент в l2, но все равно сделали не правильно. Никакой новый элемент вы не добавляете, а просто меняете значение последнего на j. Да это и не нужно делать если j != l2.data. Это нужно делать когда вы прошли весь список l2 и не нашли j.

То есть проходите по списку l1, но вам нужно добавить сам переход на следующий элемент. l1 = l1->next

Потом если l2 пустой (l2 == nullptr), то вам нужно проинициализировать список, и для этого нужно передавать указатель l2 по ссылке или указателю.

Иначе вам нужно пройтись по всему списку l2, но нужно поменять условие на l2->next != nullptr т.к. l2 точно не будет nullptr по проверке выше, а указатель на последний элемент нужен будет для добавления нового элемента.

В цикле ищем j среди элементов. Если нашли, то запишите результат поиска в bool isFind иначе переходите к следующему элементу l2 l2 = l2->next

Если isFind == false то вы должны создать для начала новый элемент типа list выделив для него память. Изменить у него значения data на j, next на NULL, а вот последнему элементу l2 вы меняете next на созданный ранее новый элемент.

Удачи!

P.s. да не надо ставить -реп :) я хоть как то помогаю

→ Ссылка