Member Avatar for andylbh

The code below is what I have done up so far.
I'm currently trying to complete one of the 4 classes I have, so the codes are incomplete and made to work at it's current stage.

Q1.
I need to have 3 different sorting criteria:
1.Sort by X (asc/desc)
2.Sort by Y (asc/desc)
3.Sort by DistFrOrigin (asc/desc)

How can I sort them?
I tried using sort( v.begin(), v.end() ) and resulted in a long list of error.

Q2.
On a side note, is the way I'm doing actually Logical?
Or there's a better way to do it?

Please advise.
Thanks in advance!

Point2D.h

class 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();
	
	void printPoint2D();
};

Point2D.cpp

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

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

//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) );
}

void Point2D::printPoint2D()
{
	cout << x << y << distFrOrigin << endl;
}

Main file.

string lines;
	vector<Point2D> v;
	
	ifstream infile("myfile.txt");
	while(!getline(infile,lines,',').eof())
	{
		if(lines=="Point2D")
		{	
			int x, y, z; 	 
			getline(infile,lines,' ');
			getline(infile,lines,'[');
			getline(infile,lines,',');
			
			stringstream s1(lines);
			s1 >> x;
			
			getline(infile,lines,' ');
			getline(infile,lines,']');
			stringstream s2(lines);
			s2 >> y;
			
			Point2D p(x,y);
			v.push_back(p);
			
			getline(infile,lines);
		}
		else if(lines=="Point3D")
		{
			getline(infile,lines);
		}
		else if(lines=="Line2D")
		{
			getline(infile,lines);
		}
		else if(lines=="Line3D")
		{
			getline(infile,lines);
		}
	}
	infile.close();

	vector<Point2D>::iterator it = v.begin();
	
	while(it != v.end())
	{
		it->printPoint2D();
		it++;
	}

mytext.txt

Point2D, [-9, -9]
Line3D, [7, 12, 3], [-9, 13, 68]
Point3D, [1, 3, 8]
Line2D, [5, 7], [3, 8]
Point2D, [3, 3]
Line3D, [7, -12, 3], [9, 13, 68]
Point3D, [6, 9, 5]
Point2D, [23, 23]
Line3D, [70, -120, -3], [-29, 1, 268]
Line3D, [25, -69, -33], [-2, -41, 58]
Point3D, [6, 9, -50]

Associative containers are kept in order. I suggest you take a look at std::set, which allows using a comparison class. This class keeps the set in order automatically.

I'm not sure how you should handle 3 different sorting criteria for 4 classes. This would end up in 12 different containers. You should also look into inheritance, make a base class and you can store multiple classes into same container.

The sort algorithm (or the std::set container) have an optional parameter which is the Compare function for the elements to be sorted. This comparison function is, by default, the less-than operator which ends up sorting things in increasing order. You simply need to make a functor (callable object) which does the kind of comparison you need for your problem (or it can be a function-pointer, but a functor is more practical). Here is an example to sort by the X value:

struct CompareByX {
  template <typename PointType>
  bool operator()(const PointType& p1, const PointType& p2) const {
    return p1.getX() < p2.getX();
  };
};

int main() {
  std::vector<Point2D> v_2D;
  // fill v_2D with values...
  //then, sort according to X:
  std::sort(v_2D.begin(), v_2D.end(), CompareByX()); //create the CompareByX functor.

  //similarly for Point3D:
  std::vector<Point3D> v_3D;
  //..
  std::sort(v_3D.begin(), v_3D.end(), CompareByX()); //you can reuse the same functor since it is template-callable.

  //you can do pretty much the same thing with a std::set (which keeps it sorted all the time):
  std::set<Point2D, CompareByX> s_2D;
  //just fill s_2D with data, no need to sort afterwards since it is always in order.
};

Just make other functors for Y and DistFrOrigin, and you are done. You can also make those functors as either classes nested in the Point2D/Point3D classes, or as static member functions of Point2D/Point3D classes. Here is an example as a static member function in the Point2D class:

class Point2D {
  //... all your other stuff...
  public:
    static bool CompareX(const Point2D& p1, const Point2D& p2) {
      return p1.x < p2.x; //notice that you have private access rights, which can be useful.
    };
};

int main() {
  std::vector<Point2D> v_2D;
  //..
  std::sort(v_2D.begin(), v_2D.end(), Point2D::CompareX);
};
Member Avatar for andylbh

Thanks alot! I was looking for this!

A question:

class Point2D {
//... all your other stuff...
public:
static bool CompareX(const Point2D& p1, const Point2D& p2) {
return p1.getX() < p2.getX();
};
};

int main() {
std::vector<Point2D> v_2D;
//..
std::sort(v_2D.begin(), v_2D.end(), Point2D::CompareX);
};

I was actually trying to work on this initially, but I got error when implementing the sort() because I tried stuffs like:

std::sort(v_2D.begin(), v_2D.end(), Point2D.CompareX);
std::sort(v_2D.begin(), v_2D.end(), Point2D->CompareX);

Can you explain to me how come it is :: in this case?
I can't seem to understand the difference between these

The :: operator is a scope-resolution operator. Because CompareX is a static member function, it is like a free function which is in the scope of the class Point2D. So, the Point2D:: means "look into the scope of Point2D for ..." (just like std:: means "look into the scope of namespace std for..."). Because it is a static function, it does not require an instance of the class (an object) to be called with. On the other hand, the two options you tried (with dot and arrow) are operators to find members of an object. They can only be used on an object (not on the class) to retrieve a member (data or function), and the dot is for an object directly while the arrow is for a pointer to an object.

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.