Using vectors to remove redundant datas.

I have a text file to take in.
Which contain datas like:

Point1 [5, 10]
Point2 [10, 11]
Point1 [5, 10]
Point3 [20, 50]
Point1 [5, 10]

If I store everything of Point1 into a vector. it works fine. But is there any way I can make things happen for the Point to only be stored once?

I tried <set> it gave me a lot of problems like no match for 'operator<' in '__x __y'

I still prefer using vector to do this.

Point.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef POINT_H
#define POINT_H 

#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <stdio.h>

using namespace std;

class Point
{
    friend ostream& operator<<(ostream&, const Point&);

    protected:
        int x, y;

    public:
        //c'tor
        Point(int xx, int yy);

        //setters
        void setX(int x1);
        void setY(int y1);

        //getters
        int getX() const {return x;};
        int getY() const {return y;};
};

Point::Point(int xx, int yy) : x(xx), y(yy)
{

}

void Point::setX(int x1)
{
    x=x1;
}

void Point::setY(int y1)
{
    y=y1;
}


Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "Point.h"
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <set>
#include <math.h>
#include <set>
#include <string.h>
#include <string>
#include <stdio.h>
#include <map>
#include <algorithm>
#include <map>

using namespace std;

class Main
{
    public: 
        void mainMenu();
        void stringToUpper(string &s);
};

void stringToUpper(string &s)
{
    for(unsigned int l=0; l < s.length(); l++)
    {
        s[l] = toupper(s[l]);    
    }
}

void Main::mainMenu()
{
    cout<<"1)   type filename and read data"<<endl;
    cout<<"2)   View data"<<endl;    
    cout<<"Q)   Enter 'Q' to quit"<<endl<<endl;
}

int main()
{
    Main main;
    char menuChoice;
    bool quit=false;
    int count = 0;

    vector<Point> p;

    while ( !quit)
    {
        main.mainMenu();
        cout << "Please enter your choice : ";
        cin>>menuChoice;
        menuChoice = toupper(menuChoice);

        switch(menuChoice)
        {
            case '1':
                {
                    string line, name;
                    char filename[50];
                    int x,y;

                    cout << "Please enter filename : ";
                    cin >> filename;

                    ifstream myfile(filename);
                    if (myfile.is_open())
                    {
                        while ( myfile.good() )
                        {
                            getline(myfile, line);
                            {      
                                for (unsigned int i = 0; i < line.size(); ++i) 
                                {
                                    if (line[i] == '[' || line[i] == ']' || line[i] == ',') 
                                    {
                                        line[i] = ' ';
                                    }
                                    istringstream in(line);
                                    in >> name >> x >> y;                                  
                                }
                                if(name == "Point1")
                                {
                                p.push_back(Point(x,y))    }                        
                            }                                
                            count++;
                        }    
                        myfile.close();
                        cout << count;
                    }
                    else cout<< "Unable to open file";
                }
                break;                             
            case '2':
                {
                cout<<"view data"<<endl;
                }                   
            case 'Q':
                cout<<"You have chosen to quit!"<<endl;
                quit=true;
                exit(0);
            default:
                cout<<"Invalid entry"<<endl<<endl;
                break;
        }
    }
}
Last edited on
Using std::set is the right thing to do.
All you need to do is provide a comparison operator< for the Points, so that it can figure out how to sort them, and which are equal.

(a < b == false && b < a == false) means a == b


Anyway.
1
2
3
4
5
6
7
8
9
10
11
12
13
class Point {
// ...
public:

    // possible code
    bool operator < (const Point &p) const
    {
        if (x == p.x)
            return y < p.y;

        return x < p.x;
    }
};


Edit: code tags.
Last edited on
Hey catfish2, thanks for your reply. How would I be able to use the setters/getters if I am using set? I am using vectors because of this.
Catfish2, is this the right way if I add one more int Z value in protected?

bool operator < (const Point &p) const
{
if (x == p.x && y == p.y)
return z < p.z;

return x < p.x;
}
Hey catfish2, thanks for your reply. How would I be able to use the setters/getters if I am using set? I am using vectors because of this.

I don't think std::set lets you modify objects after they're inserted. (For the reason that if you could do that, you'd mess up the order.)
So you can kiss your setters goodbye, but the getters will still work.

To iterate and display an std::set the old fashioned way, use:
1
2
for (std::set<Point>::const_iterator ci = mySet.begin(); ci != mySet.end(); ++ci)
    std::cout << *ci << std::endl; // an iterator is a bit like a pointer 


The new C++11 way (your compiler may not support this):
1
2
for (const Point &p: mySet) // range-based for loop
    std::cout << p << std::endl;


Catfish2, is this the right way if I add one more int Z value in protected?

Not exactly. The purpose of a good operator< is to approximate Point1 < Point2 as well as possible.
So if you have x, y, z, it should look more like:
1
2
3
4
5
6
7
8
9
10
11
12
bool operator < (const Point &p) const
{
    if (x == p.x)
    {
        if (y == p.y)
            return z < p.z;

        return y < p.y; // you miss this possibility
    }

    return x < px;
}
My iterators are fine now. Getting all the points of x,y i need. Amazing I did it that way (adding z in ) and everything came out fine lol.

How about sorting in a set then ? I need ascending / descending.

Lets say it will consider X first. and Ascending. So 1, 2, 3, 4, 4.
This is all X. Then it is sorted in place. Afterwhich it will then compare in ascending order of Y. How do i do this?
Ah I was wrong. It is only returning x and y but not Z when I use that operator < method of my own
My iterators are fine now. Getting all the points of x,y i need. Amazing I did it that way (adding z in ) and everything came out fine lol.

The anomaly caused by your original operator< will be visible when you try to add more Points with equal x and z members, but unequal y.

How about sorting in a set then ? I need ascending / descending.

The elements are sorted by using your operator<, in ascending order (but it is you who decides what makes a Point smaller than another).

So you don't sort manually, the std::set does it for you. But you can use rbegin() and rend() instead of begin() and end() to iterate from the last element to the first.

Example here:
http://cplusplus.com/reference/stl/set/rbegin/
Hmm. I am not getting my z. Weird.
This is how I am adding my Z in. Is this right? I am using it with another class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#ifndef POINT1_H
#define POINT1_H 
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <stdio.h>
using namespace std;

class Point1 : public Point
{
	friend ostream& operator<<(ostream&, const Point1&);
	
	protected:
		int z;
		double distFrOrigin;		
	public:
		void setDistFrOrigin();
		//c'tor
		Point1(int xx, int yy, int zz);
	
		//setters
		void setX(int x1);
		void setY(int y1);
		void setZ(int z1);
		
		//getters
		int getX() const {return x;};
		int getY() const {return y;};
		int getZ() const {return z;};
		
		double getScalarValue() const {return distFrOrigin;};
		
		void print(ostream& out, bool WithDistFrOrigin = false) const;
		
		struct theDist 
		{
			const Point1& data;
			theDist(const Point1& data1) : data(data1) { };
		};
		
		friend ostream& operator<<(ostream& out, const Point1::theDist& obj);
		bool operator < (const Point1 &p1) const
		{
		    if (x == p1.x)
		    {
		        if (y == p1.y)
		            return z < p1.z;
		
		        return y < p1.y; // you miss this possibility
		    }
		
		    return x < p1.x;
		}
};

Point1::Point1(int xx, int yy, int zz) : Point(xx, yy)
{
	setDistFrOrigin();
}

void Point1::setX(int x1)
{
	x=x1;
	setDistFrOrigin();
}

void Point1::setY(int y1)
{
	y=y1;
	setDistFrOrigin();
}

void Point1::setZ(int z1)
{
	z=z1;
	setDistFrOrigin();
}

void Point1::setDistFrOrigin()
{
	distFrOrigin = sqrt(x*x + y*y + z*z);
}

ostream& operator<<(ostream &out, const Point1 &p1)
{
  out << "[" << p1.x << "," << p1.y << "]";
  return out;
}
//print without dist
ostream& operator<<(ostream &out, const Point1::theDist &p1)
{
	out << "[" << p1.data.x << "," << p1.data.y << "] " << p1.data.distFrOrigin;
	return out;
}

#endif
1
2
3
4
5
6
7
8
9
10
11
Point1::Point1(int xx, int yy, int zz) : Point(xx, yy)
{
	setDistFrOrigin();
}

// should be

Point1::Point1(int xx, int yy, int zz) : Point(xx, yy), z(zz)
{
	setDistFrOrigin();
}


Also your ostream & operator << () function doesn't display the p1.z.
Topic archived. No new replies allowed.