DLL с Mergesort продолжает падать - PullRequest
0 голосов
/ 02 октября 2019

Я пытаюсь выяснить, почему моя программа продолжает сбой после ввода идентификатора, имени, адреса электронной почты и GPA. Я думаю, что это из-за функции void print() или void addItem(llist *head).

mergedll.h

#ifndef record_H_
#define record_H_
#include <iostream>
#include <string>
using namespace std;

class record;
struct litemLL;

struct llist{
    int size;
    litemLL *first;
    litemLL *last;
};

struct litemLL{
    llist *origin;
    litemLL *next;
    litemLL *prev;
    record *data;
};

class record{
public:

    int id;
    string name;
    string email;
    double gpa;

public:

    record(){ // constructor
        id = 0;
        name = "N/A";
        email = "N/A";
        gpa = 0.0;
    }

    record(const record &copy){ // copy constructor
        id = copy.id;
        name = copy.name;
        email = copy.email;
        gpa = copy.gpa;
    }

    ~record(){} // deconstructor

    record(record&& move){ // move constructor

        id = move.id;
        name = move.name;
        email = move.email;
        gpa = move.gpa;

        move.id = 0;
        move.name = "N/A";
        move.email = "N/A";
        move.gpa = 0.0;

    }

    record& operator=(const record& copyA){ // copy assignment

        if(this == &copyA){

            return *this;
        }

        id = copyA.id;
        name = copyA.name;
        email = copyA.email;
        gpa = copyA.gpa;

        return *this;
    }

    record& operator=(record&& moveA){ // move assignment

        if(this == &moveA){

            return *this;
        }

        id = moveA.id;
        name = moveA.name;
        email = moveA.email;
        gpa = moveA.gpa;

        moveA.id = 0;
        moveA.name = "N/A";
        moveA.email = "N/A";
        moveA.gpa = 0.0;

        return *this;
    }
};

litemLL *split(litemLL *head){

    litemLL *fast = head,*slow = head;
        while (fast->next && fast->next->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        litemLL *temp = slow->next;
        slow->next = NULL;
        return temp;
}

litemLL *merge(litemLL *first, litemLL *second){
    // If first linked list is empty
    if (!first)
        return second;

    // If second linked list is empty
    if (!second)
        return first;

    // Pick the smaller value
    if (first->data < second->data)
    {
        first->next = merge(first->next, second);
        first->next->prev = first;
        first->prev = NULL;
        return first;
    }
    else
    {
        second->next = merge(first, second->next);
        second->next->prev = second;
        second->prev = NULL;
        return second;
    }
}

litemLL *mergeSort(litemLL *head){

    if (!head || !head->next)
            return head;
    litemLL *second = split(head);

    //Recur for left & right halves
    head = mergeSort(head);
    second = mergeSort(second);

    // Merge the two sorted halves
    return merge(head, second);
}

void addItem(llist *head){

    litemLL *temp = new litemLL;
    temp->data = new record();

    cout << "Enter ID: ";
    cin >> temp->data->id;
    cin.ignore(1000, '\n');

    cout << "Enter Name: ";
    getline(cin, temp->data->name);

    cout << "Enter Email: ";
    getline(cin, temp->data->email);

    cout << "Enter GPA: ";
    cin >> temp->data->gpa;

    if(head->last == nullptr)
        head->last = temp;

    temp->next = head->first;

    if((head->first) != NULL)
        head->first->prev = temp;

    head->first = temp;
    temp->prev = NULL;

    head->size++;

    cout << endl;
}

void insert(llist *head, int pos){

    litemLL *temp = new litemLL();

    if(pos >= head->size || pos <= 0){
        cout << "ERROR!" << endl;
        return;
    }

    for(int i = 0; i < pos; ++i){
        temp = temp->next;
    }

    cout << "Enter ID:\t";
    cin >> temp->data->id;
    cin.ignore(1000, '\n');

    cout << "Enter Name:\t";
    getline(cin, temp->data->name);

    cout << "Enter Email:\t";
    getline(cin, temp->data->email);

    cout << "Enter GPA:\t ";
    cin >> temp->data->gpa;
}

void print(llist *head){

    litemLL *temp = head->first;
    temp->data = new record();

    while(temp != nullptr){

        cout << "ID:\t" << temp->data->id;
        cout << "NAME:\t" << temp->data->name;
        cout << "EMAIL:\t" << temp->data->email;
        cout << "GPA:\t" << temp->data->gpa;
        temp = temp->next;
    }
}

void swap(int *A, int *B)
{
    int temp = *A;
    *A = *B;
    *B = temp;
}

#endif

main.cpp

#include <iostream>
#include "mergedll.h"
using namespace std;

int main(){

    llist *head = new llist;

    for(int i = 0; i < 1; i++){
        addItem(head);
    }

    print(head);
    head->first = mergeSort(head->first);

    return 0;
}

//OUTPUT:

//    Enter ID: 12345
//    Enter Name: John
//    Enter Email: jsmith@email.com
//    Enter GPA: 3.5

//CRASHES HERE WHEN IT SHOULD BE PRINTING!!!

1 Ответ

0 голосов
/ 02 октября 2019

Ваша структура llist не имеет конструктора, и поэтому следующая строка в main будет инициализировать его по умолчанию:

llist *head = new llist;

Теперь ни один из членов объекта, на который указывает head инициализируются, и ваша программа имеет неопределенное поведение, потому что вы пытаетесь использовать их (в addItem) перед инициализацией.

Это можно исправить, указав соответствующий конструктор по умолчанию (который инициализирует каждый элемент нулями),или путем инициализации объекта с нуля при его создании:

  • Пример конструктора по умолчанию:

    struct llist {
        llist()
            : size(0)
            , first(nullptr)
            , last(nullptr)
        { }
    
        int size;
        litemLL *first;
        litemLL *last;
    };
    
  • Пример инициализации с нуля:

    llist *head = new llist();
    
...