I am attempting to go through a "Circle" structure (basically a binary tree). Each circle has an centerX, centerY, radius, and two leaf nodes. These leaves will either both be null or both be not null. There will never be one null and one not null.
I am using operator overloading to print a circle to the output stream using the SVG file format. The following is the relevant code:
circle.h:
#include <set>
#include <iostream>
using namespace std;
class Circle {
private:
double centerX, centerY, radius;
Circle* c1;
Circle* c2;
public:
static const int PAGE_DIMENSION = 200;
static const int DEFAULT_MAX_RADIUS = 15;
Circle( double x, double y, double radius, Circle* r1, Circle* r2 );
Circle( double x, double y, double radius );
Circle();
int isLeaf() const;
double getCenterX() const;
double getCenterY() const;
double area() const;
double getRadius() const;
Circle* getFirstSubcircle() const;
Circle* getSecondSubcircle() const;
bool operator<( Circle& other );
Circle* operator()( double x_in, double y_in);
Circle& operator=( Circle& rhs);
Circle* operator,( Circle& other );
double distance( Circle& rhs );
// THESE FUNCTIONS ARE NOT CLASS MEMBERS
// THEY ARE DEFINED OUTSIDE OF THE CLASS
// BUT REQUIRE ACCESS TO PRIVATE FIELDS
friend ostream& operator<<(ostream& osInput, Circle& circle);
friend ostream& operator/(ostream& osInput, Circle& circle);
friend Circle* reduce( set<Circle*>& circles);
};
circle.cpp:
#include <math.h>
#include <time.h>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <set>
#include <fstream>
#include "circle.h"
using namespace std;
Circle::Circle( double x, double y, double radius, Circle* r1, Circle* r2 )
{
centerX = x;
centerY = y;
this->radius = radius;
c1 = r1;
c2 = r2;
}
Circle::Circle( double x, double y, double radius )
{
centerX = x;
centerY = y;
this->radius = radius;
}
Circle::Circle()
{
srand(time(0));
int randomX = rand() % (PAGE_DIMENSION 1);
int randomY = rand() % (PAGE_DIMENSION 1);
int randomRadius = rand() % DEFAULT_MAX_RADIUS 1;
centerX = randomX;
centerY = randomY;
radius = randomRadius;
}
Circle* Circle::getFirstSubcircle() const
{
return c1;
}
Circle* Circle::getSecondSubcircle() const
{
return c2;
}
int Circle::isLeaf() const
{
if (c1 == NULL && c2 == NULL) {
return 1;
}
return 0;
}
ostream& operator/(ostream& osInput, Circle& circle)
{
if (circle.isLeaf()) {
osInput << " <circle cx=\"" << circle.centerX << "\" cy=\"" << circle.centerY <<"\" radius=\"" << circle.radius << "\" style=\"fill:blue;stroke:black;stroke-width:.05;fill-opacity:.1;stroke-opacity:.9\"/>\n";
}
else {
osInput << " <circle cx=\"" << circle.centerX << "\" cy=\"" << circle.centerY <<"\" radius=\"" << circle.radius << "\" style=\"fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5\"/>\n";
Circle* firstCircle = circle.getFirstSubcircle();
Circle* secondCircle = circle.getSecondSubcircle();
osInput / *firstCircle;
osInput / *secondCircle;
}
}
test.cpp:
#include <iostream>
#include <fstream>
#include <set>
#include <string>
#include <stdlib.h>
#include "circle.h"
using namespace std;
int main( int argc, char** argv ) {
Circle* circ2_1 = new Circle(45, 65, 3);
Circle* circ2_2 = new Circle(56, 55, 3);
Circle* circ2 = new Circle(11, 21, 8, circ2_1, circ2_2);
Circle* circ3 = new Circle(7, 7, 7);
Circle* circ4 = new Circle(10, 25, 11, circ2, circ3);
cout / *circ4;
}
When I run the code as it is above, I get the following as output:
<circle cx="10" cy="25" radius="11" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="11" cy="21" radius="8" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="45" cy="65" radius="3" style="fill:blue;stroke:black;stroke-width:.05;fill-opacity:.1;stroke-opacity:.9"/>
<circle cx="56" cy="55" radius="3" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
The following output is what I am expecting (based on the code within main):
<circle cx="10" cy="25" radius="11" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="11" cy="21" radius="8" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="45" cy="65" radius="3" style="fill:blue;stroke:black;stroke-width:.05;fill-opacity:.1;stroke-opacity:.9"/>
<circle cx="56" cy="55" radius="3" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="7" cy="7" radius="7" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
If I switch the last couple lines of code within the "ostream& operator/" function within the circle.cpp to the following:
osInput / *secondCircle;
osInput / *firstCircle;
The output will then be:
<circle cx="10" cy="25" radius="11" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
<circle cx="7" cy="7" radius="7" style="fill:yellow;stroke:black;stroke-width:.05;fill-opacity:.0;stroke-opacity:.5"/>
Again, this is not what I am expecting. The issue seems to be that it is only appending to ostream the first circle that is that is listed in the code, whether it is "firstCircle" or "secondCircle" that appears first. Am I wrong in thinking that it should produce the output I am expecting? Any ideas pointing me in the right direction would be much appreciated, as I have tried everything I can think of.
CodePudding user response:
For the 3-parameter Circle
constructors, you don't initialize the c1
or c2
members. This will be Undefined Behavior when you later try to dereference these values (likely a crash).