954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

vector of class objects and sorting

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]
andylbh
Newbie Poster
19 posts since Jan 2011
Reputation Points: 10
Solved Threads: 0
 

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.

Topi Ojala
Junior Poster in Training
66 posts since May 2009
Reputation Points: 13
Solved Threads: 20
 

Perhaps a custom sort on the vector might solve your problem. See attached link for ideas

http://stackoverflow.com/questions/1380463/sorting-a-vector-of-custom-objects

template<>
Junior Poster
165 posts since Feb 2011
Reputation Points: 84
Solved Threads: 26
 

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);
};
mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

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 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

andylbh
Newbie Poster
19 posts since Jan 2011
Reputation Points: 10
Solved Threads: 0
 

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.

mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

This question has already been solved

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: