Hi
This is my first DaniWeb post so I hope I get it right.
My problem is homework. I have almost got it but I'm having trouble with the pointers. The entire program will output svg code but I've tried to leave out as much as I can to reduce the amount of code. There are a number of shape classes, two have been left as stubs. One Svg class and a DataType class. The DataType class has an enumeration of shapes and a union of pointers. This is where I am getting confused. I can't change the way the driver works because code was supplied with the assignment to run the program. I know there is something wrong with the Append functions but I can't work out how to fix them. When I compile, I get the appended rectangles appearing properly above the svg header, then the header, then "89892" which I presume is an address, then the rectangle addresses, then an error "*** glibc detected *** free(): invalid pointer: 0xb7feaff4" then the closing svg tag and the word Aborted.
The output should be: the svg header, then the rectangle tags, then the svg end tag.
Thanks in advance
#include <iomanip> // output formatting
#include <vector> // vector class
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
class Path
{
public:
//stub
}; // Path
class Circle
{
public:
//stub
}; // Circle
class Rectangle
{
public:
Rectangle();
Rectangle(int x, int y, int w, int h, string c = "red", string f = "none");
void Print(ostream & out) const;
private:
int rx, ry, width, height;
string colour, fill;
};
ostream & operator<<(ostream & out, const Rectangle & rectangle);
class DataType
{
public:
enum { EMPTY, PATH, CIRCLE, RECTANGLE } SVGObj;
union
{
Path *path;
Circle *circle;
Rectangle *rectangle;
};
DataType();
DataType(const DataType &);
DataType(const Circle & obj);
DataType(const Path & obj);
DataType(const Rectangle & obj);
friend istream & operator>>(istream & in, DataType & aDataType);
friend ostream & operator<<(ostream & out,const DataType & aDataType);
};
struct LNode
{
DataType data;
LNode *next;
}*p;
typedef LNode* LNodePtr;
class Svg
{
public:
Svg();
Svg(int w, int h);
~Svg(); //destructor
void SetViewBounds(int minX, int minY);
void Head(ostream & out) const;
void Tail(ostream & out) const;
void Print(ostream & out) const;
void Append(const DataType & theDataType);
void Append(const Path & obj);
void Append(const Circle & obj);
void Append(const Rectangle & obj);
friend ostream & operator<<(ostream & out,const Svg & aList);
private:
LNodePtr head;
int size; //size of list
int myWidth;
int myHeight;
};
Rectangle::Rectangle()
{
rx = ry = 0;
width = height = 64;
colour = "blue";
fill = "none";
} // Rectangle
Rectangle::Rectangle(int x, int y, int w, int h, string c, string f)
{
rx = x;
ry = y;
width = w;
height = h;
colour = c;
fill = f;
} // Rectangle
void Rectangle::Print(ostream & out) const
{
out << "\n<rect x=\"" << rx << "\" y=\"" << ry << "\" width=\"" << width << "\" height=\"" << height
<< "\" stroke-width=\"" << 2 << "\" stroke=\"" << colour << "\" fill=\"" << fill << "\" />" << endl;
} // Rectangle Print
ostream & operator<<(ostream & out, const Rectangle & rectangle)
{
rectangle.Print( out );
return out;
} // Rectangle operator<<
// CONSTRUCTOR
DataType::DataType()
{
SVGObj = EMPTY;
}
DataType::DataType(const DataType & orig)
{
switch(orig.SVGObj)
{
case PATH:
path = new Path (*orig.path);
assert(path != NULL);
break;
case CIRCLE:
circle = new Circle (*orig.circle);
assert(circle != NULL);
break;
case RECTANGLE:
rectangle = new Rectangle (*orig.rectangle);
assert(rectangle != NULL);
break;
case EMPTY:
break;
}
SVGObj = orig.SVGObj;
}
DataType::DataType(const Rectangle & obj)
{
cout << obj;
}
ostream & operator<<(ostream& out, const DataType& aDataType)
{
out << aDataType.SVGObj ;
return out ;
}
//*************Svg member functions *********************
//constructor
Svg::Svg()
{
head = NULL;
size = 0;
}
Svg::Svg(int w, int h)
{
myWidth = w;
myHeight = h;
}
//destructor
Svg::~Svg()
{
LNodePtr temp;
while (head != NULL)
{
temp = head;
head = head-> next;
delete temp;
}
size = 0;
}
void Svg::Head(ostream & out) const // can't get variable myX to work
// myWidth and myHeight work better than setviewbounds
{
out << "Svg Head goes here" << endl;
} // svgHead
// XML CLOSING TAG
void Svg::Tail(ostream & out) const
{
out << "\n</svg>";
} // svgTail
void Svg::Append(const DataType & theDataType)
{
LNodePtr temp;
temp = new LNode;
if (temp == 0)
{
cerr <<"\n***No more memory!\n";
exit(1);
}
temp->data = theDataType;
temp->next = NULL;
if (head == NULL) //empty list
head = temp;
else //at least one node
{
LNodePtr current = head;
//traverse list
while (current->next != NULL)
current = current->next;
//insert node at end of list
current->next = temp;
}
}
void Svg::Append(const Rectangle & obj)
{
LNodePtr temp;
temp = new LNode;
if (temp == 0)
{
cerr <<"\n***No more memory!\n";
exit(1);
}
temp->data = obj;
// temp->next = NULL;
if (head == NULL) //empty list
head = temp;
else //at least one node
{
LNodePtr current = head;
//traverse list
while (current->next != NULL)
current = current->next;
//insert node at end of list
current->next = temp;
}
}
ostream & operator<<(ostream & out,const Svg & aList)
{
LNodePtr temp = aList.head;
aList.Head(out);
while(temp != NULL)
{
out << temp->data << endl;
temp = temp->next;
}
aList.Tail(out);
return out;
}
// constants
const int SIZE = 243; // 3^5 size of the image
// prototypes
void drawSierpinskiCarpet(Svg & graph, int xTL, int yTL, int width, int height);
int main()
{
Svg carpet( SIZE, SIZE ); // initialize Svg object
drawSierpinskiCarpet( carpet, 0, 0, SIZE, SIZE ); // colour the points of Julia set in the rectangl
cout << carpet;
return 0;
}
void drawSierpinskiCarpet(Svg & graph, int xTL, int yTL, int width, int height)
{
if (width > 2 && height > 2) // stop if objects are small
{
int w = width/3, h = height/3; // divide square into 9 sub-squares
Rectangle rectangle(xTL+w, yTL+h, w, h ); // create the middle rectangle
graph.Append(rectangle); // append to the graph
int i=1;// for (int i = 0; i < 3; i++)
int j=1;// for (int j = 0; j < 3; j++)
// if ( i != 1 || j != 1) // omit the middle one
drawSierpinskiCarpet ( graph, xTL+i*w, yTL+j*h, w, h ); // recursion
}
} // drawSierpinskiCarpet