我制作了一个简单的代码,可以生成一些随机用户并对其进行处理 形成一些琐碎的商业图表。 代码与列表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。 感谢。
答案 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;
}