Программа завершается со значением 3221225477 C++

В структуре содержится информация о названии книги, авторе книги и года издания. Нужно удалить книги по заданному автору, используя класс List. Методом в данном случае будет Del. Допустим, список состоит из таких элементов:

(Book C / Author C / 2010, Book D / Author D / 2015, Book A / Author A / 2000, Book B / Author B / 2005)

Как только программа начинает запрашивать ввод для удаления книги (элемента списка) по заданному автору, то она завершается со значением 3221225477. Что может быть не так в этой программе?

Обновлено. Код сократил на несколько десятков строк. Если где-то можно ещё сократить, то вопрос будет отредактирован.

Ожидаемый результат после удаления элемента списка по автору, например, Author A:

(Book C / Author C / 2010, Book D / Author D / 2015, Book B / Author B / 2005)

Конечный результат:

List L:
(Book C / Author C / 2010, Book A / Author A / 2000, Book B / Author B / 2005)

Вставляем новый элемент списка L на 2-ю позицию (индекс 1)
Input position: 2

Input new data:
Bookname - Book D
Author - Author D
Year - 2015

List L до удаления третьего элемента (индекс 2):
(Book C / Author C / 2010, Book D / Author D / 2015, Book A / Author A / 2000, Book B / Author B / 2005)

Input author:
--------------------------------
Process exited after 17.94 seconds with return value 3221225477
Для продолжения нажмите любую клавишу . . .

Код программы:

struct Book {
    string book_name; // название книги
    string author; // автор книги
    int year; // год издания
    Book * next, * prev;
};

class List {
    // Голова, хвост
    Book * Head, * Tail;
    // Количество элементов
    int Count;
      
    public:
        // Конструктор
        List();

        // Конструктор копирования
        List(const List&);

        // Деструктор
        ~List();
             
        // далее определены методы, но я их не указал, чтобы сократить 
        // код до минимального воспроизводимого примера, если это возможно
};

// Конструктор
List::List() {
    // Изначально список пуст
    Head = Tail = NULL;
    Count = 0;
}

// Конструктор копирования
List::List(const List & L) {
    Head = Tail = NULL;
    Count = 0;
    
    // Голова списка, из которого копируем
    Book * temp = L.Head;

    // Пока не конец списка
    while (temp != 0) {
        // Передираем данные
        AddTail(*temp);
        temp = temp->next;
    }
}

// Деструктор
List::~List() {
    // Удаляем все элементы
    DelAll();
}

// Удаление элемента, если параметр не указывается,
// то функция его запрашивает
void List::Del() {
    string del_author;
    cout << "Input author: ";
    getline(cin, del_author);
    
    // Счетчик
    int i = 1;
    
    Book * Del = Head;

    while (true) {
        // Доходим до элемента, который удаляется
        Del = Del->next;
        i++;
        if (del_author == Del->author)
            break;
    }
    
    // Доходим до элемента,
    // который предшествует удаляемому
    Book * PrevDel = Del->prev;
    // Доходим до элемента, который следует за удаляемым
    Book * AfterDel = Del->next;
    
    // Если удаляем не голову
    if (PrevDel != 0 && Count != 1)
        PrevDel->next = AfterDel;
    // Если удаляем не хвост
    if (AfterDel != 0 && Count != 1)
        AfterDel->prev = PrevDel;
    
    // Удаляются крайние?
    if (i == 1)
        Head = AfterDel;
    if (i == Count)
        Tail = PrevDel;
    
    // Удаление элемента
    if (del_author == Del->author)
        delete Del;
    else
        cout << "No such author!\n\n";
    
    Count--;
}

// Вставка элемента, если параметр не указывается,
// то функция его запрашивает
void List::Insert(int pos) {
    // если параметр отсутствует или равен 0, то запрашиваем его
    if (pos == 0) {
        cout << "Input position: ";
        cin >> pos;
        cin.ignore();
        cout << "\n";
    }
    
    // Позиция от 1 до Count?
    if (pos < 1 || pos > Count + 1) {
        // Неверная позиция
        cout << "Incorrect position !!!\n";
        return;
    }
    
    // Если вставка в конец списка
    if (pos == Count + 1) {
        // Вставляемые данные
        Book new_element;
        cout << "Input new data:\n";

        cout << "Bookname - ";
        getline(cin, new_element.book_name);

        cout << "Author - ";
        getline(cin, new_element.author);

        cout << "Year";
        cin >> new_element.year;

        // Добавление в конец списка
        AddTail(new_element);
        return;
    }
    else if (pos == 1) {
        // Вставляемые данные
        Book new_element;
        cout << "Input new data:\n";

        cout << "Bookname - ";
        getline(cin, new_element.book_name);

        cout << "Author - ";
        getline(cin, new_element.author);

        cout << "Year - ";
        cin >> new_element.year;

        cout << "\n";

        // Добавление в начало списка
        AddHead(new_element);
        return;     
    }
    
    // Счетчик
    int i = 1;
    
    // Отсчитываем от головы n - 1 элементов
    Book * Ins = Head;
    
    while (i < pos) {
        // Доходим до элемента,
        // перед которым вставляемся
        Ins = Ins->next;
        i++;      
    }
    
    // Доходим до элемента,
    // который предшествует
    Book * PrevIns = Ins->prev;
    
    // Создаем новый элемент
    Book * temp = new Book;
    
    // Вводим данные
    cout << "Input new data:\n";

    cout << "Bookname - ";
    getline(cin, temp->book_name);

    cout << "Author - ";
    getline(cin, temp->author);

    cout << "Year - ";
    cin >> temp->year;

    cout << "\n";
    
    // настройка связей
    if (PrevIns != 0 && Count != 1)
        PrevIns->next = temp;
    
    temp->next = Ins;
    temp->prev = PrevIns;
    Ins->prev = temp;
    
    Count++;
}

// Добавление в начало списка
void List::AddHead(Book &bk) {
    // новый элемент
    Book * temp = new Book;
    
    // Предыдущего нет
    temp->prev = 0;

    // Заполняем данные
    temp->book_name = bk.book_name;
    temp->author = bk.author;
    temp->year = bk.year;

    // Следующий - бывшая голова
    temp->next = Head;
    
    // Если элементы есть?
    if (Head != 0)
        Head->prev = temp;
    
    // Если элемент первый, то он одновременно и голова и хвост
    if (Count == 0)
        Head = Tail = temp;
    else
        // иначе новый элемент - головной
        Head = temp;
     
    Count++;
}

// Добавление в конец списка
void List::AddTail(Book &bk) {
    // Создаем новый элемент
    Book * temp = new Book;

    // Следующего нет
    temp->next = 0;

    // Заполняем данные
    temp->book_name = bk.book_name;
    temp->author = bk.author;
    temp->year = bk.year;

    // Предыдущий - бывший хвост
    temp->prev = Tail;
    
    // Если элементы есть?
    if (Tail != 0)
        Tail->next = temp;
    
    // Если элемент первый, то он одновременно и голова и хвост
    if (Count == 0) {
        Head = Tail = temp;
    }
    else {
        // иначе новый элемент - хвостовой
        Tail = temp;
    }
     
    Count++;
}

// Печать списка
void List::Print() {
    // Если в списке присутствуют элементы, то пробегаем по нему
    // и печатаем элементы, начиная с головного
    if (Count != 0) {
        Book * temp = Head;
        cout << "(";
        while (temp->next != 0) {
            cout << temp->book_name << " / ";
            cout << temp->author << " / ";
            cout << temp->year << ", ";
            temp = temp->next;
        }
        
        cout << temp->book_name << " / ";
        cout << temp->author << " / ";
        cout << temp->year << ")";
    }

    cout << "\n\n";
}

// Тестовый пример
int main() {
    setlocale(LC_CTYPE, "rus");

    List L;
    
    const int n = 3;
    Book data[n];

    data[0].book_name = "Book A";
    data[0].author = "Author A";
    data[0].year = 2000;

    data[1].book_name = "Book B";
    data[1].author = "Author B";
    data[1].year = 2005;

    data[2].book_name = "Book C";
    data[2].author = "Author C";
    data[2].year = 2010;

    // Добавляем элементы, стоящие на четных индексах, в голову
    // на нечетных - в хвост
    for (int i = 0; i < n; i++)
        if (i % 2 == 0)
            L.AddHead(data[i]);
        else
            L.AddTail(data[i]);
            
    // Распечатка списка
    cout << "List L:\n";
    L.Print();
    
    // Вставка элемента в список
    cout << "Вставляем новый элемент списка L на 2-ю позицию (индекс 1)\n";
    L.Insert();

    // Удаляем из списка Book A / Author A / 2000 на третьей позиции
    cout << "List L до удаления третьего элемента (индекс 2):\n";
    L.Print();

    L.Del();

    cout << "List L после выполнения команды L.Del():\n";
    L.Print();
}

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

Автор решения: AlexanderSt

Вот в этом цикле

while (true) {
    // Доходим до элемента, который удаляется
    Del = Del->next;
    i++;
    if (del_author == Del->author)
        break;
}

очень было бы неплохо проверять, а существует ли Del->Next. Программа падает из-за того, что вы пытаетесь разыменовывать nullptr. И у вас первый элемент списка не участвует в сравнении - вы сразу делаете Del = Head->Next; по сути, а потом только проверяете значение if (del_author == Del->author)

→ Ссылка