Member Avatar for andylbh

Line2D Points is made up of Point2D x and y

Line2D.h

#ifndef LINE2D__H
#define LINE2D__H

#include <iostream>
#include <fstream>
#include <string.h>
#include <ostream>
#include <sstream>
#include <cstdio>
#include <vector>
#include <set>
#include <cstdlib>
#include <ctype.h>
#include "Point2D.h"

using namespace std;

class Line2D
{
	friend ostream& operator<<(ostream&, const Line2D&);
	
	private:
	//Declarations
	Point2D pt1;
	Point2D pt2;
	
	protected:
	//Declarations
	double length;
	//Functions
	void setLength();
	
	public:
	//Constructor
	Line2D();
	Line2D(Point2D,Point2D);
	
	//Get Methods
	Point2D getPt1();
	Point2D getPt2();
	double getScalarValue();
	
	//Set Methods
	void setPt1(Point2D);
	void setPt2(Point2D);
};

#endif

Line2D.cpp

#include <iostream>
#include <fstream>
#include <ostream>
#include <iomanip>
#include <string.h>
#include <sstream>
#include <cstdio>
#include <vector>
#include <set>
#include <cstdlib>
#include <ctype.h>
#include <math.h>
#include "Line2D.h"
#include "Point2D.h"

using namespace std;

Line2D::Line2D()
{
}

Line2D::Line2D(Point2D pt1, Point2D pt2)
{
	this->pt1=pt1;
	this->pt2=pt2;
	setLength();
	length = getScalarValue();
}

void Line2D::setLength()
{
	length = sqrt( pow(pt1.getX()-pt2.getX(),2) + pow(pt1.getY()-pt2.getY(),2) );
}

Point2D Line2D::getPt1()
{
	return pt1;
}

Point2D Line2D::getPt2()
{
	pt2.getX();
	pt2.getY();
	return pt2;
}

void Line2D::setPt1(Point2D pt1)
{
	this->pt1=pt1;
	setLength();
}

void Line2D::setPt2(Point2D pt2)
{
	this->pt2=pt2;
	setLength();
}

double Line2D::getScalarValue()
{
	return length;
}

ostream& operator<<(ostream &out, const Line2D &l2d)
{
	out << l2d.pt1 << l2d.pt2 << l2d.length << endl;
	return out;
}

Point2D.h

#ifndef POINT2D__H
#define POINT2D__H

#include <iostream>
#include <ostream>
#include <fstream>
#include <string.h>
#include <sstream>
#include <cstdio>
#include <vector>
#include <set>
#include <cstdlib>
#include <ctype.h>

using namespace std;

class Point2D
{

	friend ostream& operator<<(ostream&, const Point2D&);
	private:
	
	protected:
	//Declarations
	int x;
	int y;
	double distFrOrigin;	
	//Function
	void setDistFrOrigin();

	public:
	//Constructor
	Point2D();
	Point2D(int,int);
	
	//Set Methods
	void setX(int);
	void setY(int);
	
	//Get Methods
	int getX();
	int getY();
	double getScalarValue();
};

#endif

Point2D.cpp

#include <iostream>
#include <ostream>
#include <iomanip>
#include <fstream>
#include <string.h>
#include <sstream>
#include <cstdio>
#include <vector>
#include <set>
#include <cstdlib>
#include <ctype.h>
#include <math.h>
#include "Point2D.h"

using namespace std;

//Constructor
Point2D::Point2D()
{
	x=0;
	y=0;
}

Point2D::Point2D(int x, int y)
{
	this->x=x;
	this->y=y;
	setDistFrOrigin();
}

//Set Method
void Point2D::setX(int x)
{
	this->x=x;
	setDistFrOrigin();
}

void Point2D::setY(int y)
{
	this->y=y;
	setDistFrOrigin();
}

//Get Method
int Point2D::getX()
{
	return x;
}

int Point2D::getY()
{
	return y;
}

double Point2D::getScalarValue()
{
	return distFrOrigin;
}

//Function
void Point2D::setDistFrOrigin()
{
	distFrOrigin = sqrt( pow(x,2) + pow(y,2) );
}

ostream& operator<<(ostream &out, const Point2D &p2d)
{
	out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]" << setw(3) << "" << p2d.distFrOrigin << endl;
	return out;
}

Main.cpp Partial Codes

Point2D p1(-9,-9);
Point2D p2(-99,-99);	
Line2D l(p1,p2);		
cout << l.getPt1();

I get this output:

[  -9,  -9]   12.728

What's wrong here?
I just wanted to get Point1 Value, which is -9, -9
but it gave me Point2D's distFrOrigin too.
And somehow the display formatting is similar to the Point2D's overloaded ostream<<
How can I solve this?
I'm stuck at this for quite awhile.

Need help and advise
Thanks in advance!

Recommended Answers

All 8 Replies

out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]" << setw(3) << "" << p2d.distFrOrigin << endl;

When you are overloading ofstream you made it to output distFrOrigin. You should have overloaded it like this:

out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]" << setw(3) << "" << endl; 

without making it output distance

Member Avatar for andylbh

But I'm also required to output distFrOrigin for point2d
Is there a way to "unrelated" these 2 overloaded ostream?
They seem kinda connected.. and interfere with what I want to achieve.

Here:
If i removed displaying DistFrOrigin, my output will be wrong

Point2D's Output

X    Y    Dist. Fr Origin
-----------------------------
[  -9,  -9]
[   3,   3]
[  23,  23]

Line2D's Output;

X-1  Y-1  X-2  Y-2    Length
----------------------------------------------------
[   5,   7]
[   3,   8]
2.236

The correct output should be

X-1  Y-1  X-2  Y-2    Length
----------------------------------------------------
[   5,   7] [   3,   8] 2.236

and the Point2D should display the DistFrOrigin

You don't have to overload operators. You can just use plain ol' cout without overloading.

And please post whole main function

Member Avatar for andylbh

If I remove the operator>> overloading,
I'll get an error from trying to cout Line2D's pt1 and pt2:
error: no match for 'operator<<' in 'std::cout << l. Line2D::getPt1()'

int main()
{
	
	Point2D p1(-9,-9);
	Point2D p2(-99,-99);	
	Line2D l(p1,p2);
	Point3D p21(-9,-9,-9);
	
	cout << "Point2D Sample Data" << endl;
	cout << p1.getX() << endl;
	cout << p1.getY() << endl;
	cout << p2.getX() << endl;
	cout << p2.getY() << endl << endl;

	cout << "Point3D Sample Data" << endl;
	cout << p21.getX() << endl;
	cout << p21.getY() << endl;
	cout << p21.getZ() << endl << endl;
	
	cout << "Line3D Sample Data" << endl;
	cout << l.getPt1() << l.getPt2() << endl << endl; //Error Here
	
	return 0;
}

and if I overload the operator>>
it affects my output in Line2D.

The easiest solution is surely to use simple print() functions instead of overloads, as follows:

//in the header:
class Point2D {
  //...
    void print(ostream& out, bool WithDistFrOrigin = false) const;
};


//in the .cpp file:
void Point2D::print(ostream& out, bool WithDistFrOrigin) const {
  out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]";
  if(WithDistFrOrigin)
    out << setw(3) << "" << p2d.distFrOrigin << endl;
};

This way, if you just call "print" on your point (passing the output-stream), you will get the output without the distance from origin, but if you add a "true" value to the call, you will get the distance from origin output as well.

If you absolutely want to use the >> operator on your Point2D objects, then you need an additional little trick. Operator overloads are selected based on the type of the parameters (and the number of parameters is fixed, so you can't add a flag to do one or the other printing method). So, in order to select different printing methods, you have to change the type of your object, which is actually quite trivial to do with a simple nested class:

class Point2D
{
  protected:
    //Declarations
    int x;
    int y;
    double distFrOrigin;	
    //Function
    void setDistFrOrigin();

  public:
    //Constructor
    Point2D(int aX = 0,int aY = 0); //use default parameters instead of 2 constructors.

    //Set Methods
    void setX(int aX); //use parameter names in prototypes to be more descriptive. 
    void setY(int aY);

    //Get Methods
    //If a member function does not modify the object, 
    //   mark it as 'const'.
    //Trivial functions can be implemented inline (inside the declaration): 
    int getX() const { return x; }; 
    int getY() const { return y; }; 
    double getScalarValue() const { return distFrOrigin; };

    friend ostream& operator<<(ostream& out, const Point2D& obj);

    //create a simple nested class that refers to a Point2D object: 
    struct WithDist {
      const Point2D& data;
      WithDist(const Point2D& aData) : data(aData) { };
    };

    //Create an overload for that object:
    friend ostream& operator<<(ostream& out, const Point2D::WithDist& obj);
};


Point2D::Point2D(int aX, int aY) : x(aX), y(aY) //prefer the "initialization list"
{
  setDistFrOrigin();
}

//Set Method
void Point2D::setX(int aX)
{
  x=aX; //if you use unique names for parameters, you won't need the 'this->'
  setDistFrOrigin();
}

void Point2D::setY(int aY)
{
  y=aY;
  setDistFrOrigin();
}

//Function
void Point2D::setDistFrOrigin()
{
  distFrOrigin = sqrt( x * x + y * y ); //using pow() in this context is just wasteful.
}

//The main overload is used to print without the distance value:
ostream& operator<<(ostream &out, const Point2D &p2d)
{
  out << "[" << setw(4) << p2d.x << "," << setw(4) << p2d.y << "]";
  return out;
}

//The second overload is used to print with the distance value:
ostream& operator<<(ostream &out, const Point2D::WithDist &p2d)
{
  out << "[" << setw(4) << p2d.data.x << "," << setw(4) << p2d.data.y << "]" << setw(3) << "" << p2d.data.distFrOrigin; //You should avoid making new lines inside an overloaded << operator (it is hidden and counter-intuitive).
  return out;
}


//Use case:
int main() {
  Point2D pt(-9,-9);

  cout << pt << endl;                    //Output: [  -9,  -9]
  cout << Point2D::WithDist(pt) << endl; //Output: [  -9,  -9]  12.728
  return 0;
};

You can see that I have also corrected several little stylish issues with your code.

Additionally, I have to remark on two big "good coding practices" violations that your code exhibits. First, you should never #include, in a header file, any more headers than you actually need in you declaration. In your code, you have this huge list of headers that you include in every source file you have, that is bad. The "principle of minimal requirement" is very important in coding, and it applies here. When someone uses your header, you require that a whole slur of headers be #included as well (or imported), why? Only include the few headers you need to complete the declaration of the class, then in the cpp, include the additional headers you need to implement the class functions, keep it to a minimum.

Second, you did "using namespace std;" in a header file. This is very bad. On a very-small project or course homework it might be acceptable, but in general, learn to avoid doing this. The reason is that this statement imports everything from the std namespace into the scope where it appears. When in a header file, that scope is the global scope, and it is the scope of any code that #includes that header, which means you are importing the entire std namespace in the entire code. The point of namespaces is to avoid name-clashes (i.e. things of the same name can be confused for one-another), when you import a namespace, you destroy that name-protection feature. So, ideally, you should avoid "using namespace .." statements almost always, and if you use them, it should be either in cpp files only and/or inside a function body (not at global or namespace scope).

Hi andy,
While helpful, sergent and mike missed the original problem: your main() failed to call p1.setDistFrOrigin() before printing it, so you were getting whatever garbage happened to be in that memory location.

Also, if I recall correctly, since pow() is written to support non-integer exponent values, it's not necessarily very efficient. For Point2D, just use sqrt(x*x + y*y), and for Line2D, consider using a couple of temporary values to make your expression more readable.

@raptr_dflo: the setDistFrOrigin() is a private function that is called in the constructors and in every set() function of the Point2D class. So, the distance value that he gets is not garbage, he actually handled this problem quite well (making setDistFrOrigin() private and calling it at every modification of the data, to keep it consistent at all times). You seem to have missed the original problem, that is, how to print his Point2D class in two different ways (with and without the distance value after), and I provided two solutions to that problem.

You are right about pow() being inefficient here. I did point that out in the code I posted. For small, integer exponents, it is always more efficient to multiply the values out instead of making a call to pow().

Member Avatar for andylbh

thanks guys for the help and advice!
@mike_2000_17 thanks alot for the effort and help!
help me out alot and i've learnt afew new stuffs w/ the codes you've edited!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.