代码运行完美但从main()返回时崩溃

时间:2016-04-23 20:52:26

标签: c++ algorithm data-structures

我制作了一个简单的代码,可以生成一些随机用户并对其进行处理 形成一些琐碎的商业图表。 代码与列表STL完美配合,但我必须自己实现链表,我发现了问题。

程序运行完美..它甚至可以产生完美的所需输出但是在最后一行代码后崩溃,我试图找出问题所在但却失败了。

这是我的代码

#include "Class.h"
#include <stdlib.h>
class Node
{
    private:
        customer data;
        Node *next;
    public:
        /*Nodes constructors*/
        Node(){next=nullptr;}
        Node(customer X)
        {
            data=X;
            next=nullptr;
        }
        /*Data setters and getters*/
        void set_Data(customer X)
        {data = X;}
        customer get_Data()
        {return data;}
        /*next setters and getters*/
        void set_next(Node * X){next=X;}
        Node* get_next(){return next;}


};

class List
{
    private:
        Node * head;
        Node * tail;
        int counter;
    public:
        /*Constructors*/
        List(){head=nullptr;tail=head;counter=0;}
        /*Checks if the list is empty*/
        bool isEmpty()
        {
            if (head==nullptr)
                return true;
            return false;
        }
        /*front manipulation*/
        void add_Front(customer item)
        {
            if (isEmpty())
            {
                head = new Node(item);
                tail = head;
                counter++;
            }
            else{
            Node * nw= new Node(item);
            nw ->set_next(head);
            head=nw;
            counter++;
            }
        }
        void pop_Front()
        {
            if (isEmpty())
                return;
            if (head==tail)
            {
                delete head;
                delete tail;
                counter--;
                return;
            }
            Node * temphead=head;
            head=head->get_next();
            delete temphead;
            counter--;
        }
        /*End Manipulation*/
        void add_End(customer X)
        {
            if(isEmpty()){
                add_Front(X);
                counter++;}
            else
            {
                Node * temp=new Node(X);
                tail->set_next(temp);
                tail=temp;
                counter++;
            }
        }

        /*freeing the whole list*/
        void Clear()
        {
            while (!isEmpty())
                pop_Front();
        }

        /*Destructor*/
        ~List(){Clear();}

        /*Extras*/
        int get_Size(){return counter;}
        customer get_Front(){return head->get_Data();}
        customer get_End(){return tail->get_Data();}

};

    using namespace std;
bool generate_pie(int slices_number,string slices_names[],int slices_values[],string title);
bool Age_Pie(List Data,int AgeCategory);
int main()
{
    List Data;
    int numberofelements;
    cout<<"How many customers you wanna randomly generate? : ";
    cin >> numberofelements;
    srand(time(NULL));
    for (int i=0; i<numberofelements; i++)
    {
        customer temp;
        temp.random_customer();
        Data.add_Front(temp);

    }
    Age_Pie(Data,1);
    return 0;

}

bool Age_Pie(List Data,int AgeCategory)
{
    int Product_Percentage[6]={0};
    int tempsize= Data.get_Size();
    for (int i =0; i<tempsize; i++)
    {

        customer temp = Data.get_Front();
        Data.pop_Front();
        if (temp.get_age()==AgeCategory)
        {
            switch (temp.get_interrest())
            {
            case 1:Product_Percentage[0]++;break;
            case 2:Product_Percentage[1]++;break;
            case 3:Product_Percentage[2]++;break;
            case 4:Product_Percentage[3]++;break;
            case 5:Product_Percentage[4]++;break;
            }
        }
        else
            Product_Percentage[5]++;
        Data.add_End(temp);
    }

    string Products[]={"Product 1","Product 2","Product 3","Product 4","Product 5","Didn\'t choose"};
    generate_pie(6,Products,Product_Percentage,"The Age Category "+to_string(3)+" Chose these products");


}


bool Product_Pie(List Data, int Chosen_product)
{
    int AgeCategory_Percentage[5]={0};
    int Datasize = Data.get_Size();
    for(double i=0; i<Datasize-1;i++)
    {
        customer dummy = Data.get_Front();
        int temp_interrest = dummy.get_interrest();
        int temp_agecat = dummy.get_age();
        Data.pop_Front();
        if (temp_interrest==Chosen_product)
        {

        switch (temp_agecat){
        case 0:AgeCategory_Percentage[0]++;break;
        case 1:AgeCategory_Percentage[1]++;break;
        case 2:AgeCategory_Percentage[2]++;break;
        case 3:AgeCategory_Percentage[3]++;break;
        }
        }
        else
            AgeCategory_Percentage[4]++;

        Data.add_End(dummy);
    }
    string Ages[]={"18 To 25","26 To 40","41 To 61","Above 60","Not Chosen"};

    generate_pie(5,Ages,AgeCategory_Percentage,"Product #"+to_string(Chosen_product+1)+" Statistics");
    return true;
}


bool generate_pie(int slices_number,string slices_names[],int slices_values[],string title)
{
    /* the function takes the number of pie slices and its names with values
     * and the pie chart title
     * writes an HTML with JS that creates the chart
     * using the googlecharts API*/

    ofstream html;
    html.open ("report.html");
    html << "<html>\n\t<head>\n"
            "\t\t<!--Load the AJAX API-->\n"
            "\t\t<script type=\"text/javascript\" src=\"https://www.gstatic.com/charts/loader.js\"></script>\n"
            "\t\t<script type=\"text/javascript\">\n\n"
            "\t\t// Load the Visualization API and the corechart package.\n"
            "\t\tgoogle.charts.load('current', {'packages':['corechart']});\n\n"
            "\t\t// Set a callback to run when the Google Visualization API is loaded.\n"
            "\t\tgoogle.charts.setOnLoadCallback(drawChart);\n\n"
            "\t\t// Callback that creates and populates a data table,\n"
            "\t\t// instantiates the pie chart, passes in the data and\n"
            "\t\t// draws it.\n\t\tfunction drawChart() {\n\n"
            "\t\t\t// Create the data table.\n"
            "\t\t\tvar data = new google.visualization.DataTable();\n"
            "\t\t\tdata.addColumn('string', 'Category');\n"
            "\t\t\tdata.addColumn('number', 'Percentage');\n"
            "\t\t\tdata.addRows([\n";

            for (int i=0;i<slices_number;i++)
                html << "\t\t\t\t['"<<slices_names[i]<<"', "<<slices_values[i]<<"],\n";

            html <<"\t\t\t]);\n\n"
            "\t\t\t// Set chart options\n"
            "\t\t\tvar options = {'title':'"<<title<<"','width':400,'height':300,is3D: true,};\n\n"
            "\t\t\t        // Instantiate and draw our chart, passing in some options.\n"
            "\t\t\tvar chart = new google.visualization.PieChart(document.getElementById('chart_div'));\n"
            "\t\t\tchart.draw(data, options);\n"
            "\t\t  }\n"
            "\t\t</script>\n"
            "\t</head>\n\n"
            "\t<body>\n"
            "\t\t<!--Div that will hold the pie chart-->\n"
            "\t\t<div id=\"chart_div\"></div>\t\n"
            "</body>\n"
            "</html>";

    return true;
}

您可以跳过generate_pie函数,因为它已经正常工作。 我觉得发布整个代码并不合适,但我开始使用Stackoverflow。 感谢。

1 个答案:

答案 0 :(得分:1)

如果列表中有一个元素,则pop_Front会中断:

    void pop_Front()
    {
        if (isEmpty())
            return;
        if (head==tail)
        {
            delete head;
            delete tail;
            counter--;
            return;
        }
        Node * temphead=head;
        head=head->get_next();
        delete temphead;
        counter--;
    }

您尝试删除两次相同的地址。应该是什么:

    void pop_Front()
    {
        if (isEmpty())
            return;
        if (head==tail)
        {
            delete head;
            head = tail = nullptr;  // optional
            counter--;
            return;
        }
        Node * temphead=head;
        head=head->get_next();
        delete temphead;
        counter--;
    }

破解演示:http://ideone.com/afg7se 工作演示:http://ideone.com/mJ489F

---编辑:Per Paul McKenzie的评论

Age_Pie(Data,1);

这会将列表的副本传递给Pie函数,默认情况下,它将是指向相同位置的所有相同节点。这意味着在销毁临时副本时,它将释放整个列表,因此您最终会多次删除所有内容。

您需要通过引用/指针传递,或者需要为List类实现复制构造函数或operator =。

---编辑2:

更新了现场演示以包含复制操作符:

    /*copy operator*/
    List& operator=(const List& rhs)
    {
        Clear();
        Node* temp = rhs.head;
        while (temp) {
            add_End(temp->get_Data());
            temp = temp->get_next();
        }
        return *this;
    }