Trouble in using std::map and its find member function

S

Saeed Amrollahi

Dear All C++ Programmers

Hello

I am Saeed Amrollahi. I am a software engineer in
Tehran Sewerage Company. I try to use std::map and map::find member
function. I
use Visual Studio .NET. my program uses two MFC classes: CRect and
CPoint
which represents Rectangle and Point concepts (as usual) and a user
defined class called GISCode which represents Global Information
System's code of Tehran city:
class GISCode
{
friend bool operator<(const GISCode&, const GISCode&);
public:
GISCode(const std::string&);
operator std::string() const; // get code
const std::string GetCode() const; // get code
// Equality Operations (generated)
bool operator==(const GISCode&) const;
bool operator!=(const GISCode&) const;
// Exception class(es)
class CodeError : public std::logic_error {
public:
CodeError(const std::string& = "");
const char* what() const;
private:
const std::string Code;
const std::string ErrMsg;
};
private:
void CheckCode(const std::string&) const;
std::string Code;
};

Tehran is a metropolitan city and contains 1080 of
these codes. I have to implement a program which shows
these codes on screen graphically in rectangles and by
each click on rectangle extracts GISCode
and finally shows a digging map of sewerage piping.
I use the following data structure:
map<CRect, GISCode> m;
I should implement a function object called
PointInRect:
// Function object for determining is a point in Rect?
class PointInRect {
public:
PointInRect(const CPoint pp) : p(pp) {}
bool operator()(const CRect& r) { return r.PtInRect(p) == TRUE ?
true : false;}
private:
const CPoint p;
};
at first I try to implement the following function:
void CTehranCityView::OnLButtonDblClk(UINT nFlags,
CPoint point)
{
map<CRect, GISCode> m = pDoc->GISRect;
// very naive implementation
find_if(m.begin(), m.end(),
PointInRect(...)); // fail!
I failed to use function object properly. My first
question is how to use such fair complex function
object in map?
After that I try to fill a vector with key elements of
map and then find CRect object in the vector using
function object:
void CTehranCityView::OnLButtonDblClk(UINT nFlags,
CPoint point)
{
vector<CRect> v;
for (map<CRect, GISCode>::const_iterator cit1 = m.begin(); cit1 !=
m.end(); cit1++) {
v.push_back(cit1->first);
}
vector<CRect>::const_iterator cit2 =
find_if(v.begin(), v.end(), PointInRect(point)); //(1)
if (cit2 != v.end()) {
map<CRect, GISCode>::const_iterator
cit3 = m.find(*cit2); //(2)
if (cit3 != m.end()) //(3)
GISCode c = cit3->second;
}
CFormView::OnLButtonDblClk(nFlags, point);
}

why the code at line (1) works?
Unfortunately at the line (2) cit3 == m.end() and I
can't extract the GISCode (at line (3)). The map is
filled by codes already.

how to solve this problem?

Regards,
Saeed Amrollahi
 
M

Mike Wahler

Saeed Amrollahi said:
Dear All C++ Programmers

Hello

I am Saeed Amrollahi. I am a software engineer in
Tehran Sewerage Company. I try to use std::map and map::find member
function. I
use Visual Studio .NET. my program uses two MFC classes: CRect and
CPoint
which represents Rectangle and Point concepts (as usual) and a user
defined class called GISCode which represents Global Information
System's code of Tehran city:
class GISCode
{
friend bool operator<(const GISCode&, const GISCode&);
public:
GISCode(const std::string&);
operator std::string() const; // get code
const std::string GetCode() const; // get code
// Equality Operations (generated)
bool operator==(const GISCode&) const;
bool operator!=(const GISCode&) const;
// Exception class(es)
class CodeError : public std::logic_error {
public:
CodeError(const std::string& = "");
const char* what() const;
private:
const std::string Code;
const std::string ErrMsg;
};
private:
void CheckCode(const std::string&) const;
std::string Code;
};

Tehran is a metropolitan city and contains 1080 of
these codes. I have to implement a program which shows
these codes on screen graphically in rectangles and by
each click on rectangle extracts GISCode
and finally shows a digging map of sewerage piping.
I use the following data structure:
map<CRect, GISCode> m;
I should implement a function object called
PointInRect:
// Function object for determining is a point in Rect?
class PointInRect {
public:
PointInRect(const CPoint pp) : p(pp) {}
bool operator()(const CRect& r) { return r.PtInRect(p) == TRUE ?
true : false;}
private:
const CPoint p;
};
at first I try to implement the following function:
void CTehranCityView::OnLButtonDblClk(UINT nFlags,
CPoint point)
{
map<CRect, GISCode> m = pDoc->GISRect;
// very naive implementation
find_if(m.begin(), m.end(),
PointInRect(...)); // fail!
I failed to use function object properly. My first
question is how to use such fair complex function
object in map?
After that I try to fill a vector with key elements of
map and then find CRect object in the vector using
function object:
void CTehranCityView::OnLButtonDblClk(UINT nFlags,
CPoint point)
{
vector<CRect> v;
for (map<CRect, GISCode>::const_iterator cit1 = m.begin(); cit1 !=
m.end(); cit1++) {
v.push_back(cit1->first);
}
vector<CRect>::const_iterator cit2 =
find_if(v.begin(), v.end(), PointInRect(point)); //(1)
if (cit2 != v.end()) {
map<CRect, GISCode>::const_iterator
cit3 = m.find(*cit2); //(2)
if (cit3 != m.end()) //(3)
GISCode c = cit3->second;
}
CFormView::OnLButtonDblClk(nFlags, point);
}

why the code at line (1) works?
Unfortunately at the line (2) cit3 == m.end() and I
can't extract the GISCode (at line (3)). The map is
filled by codes already.

how to solve this problem?


MFC is not standard, thus not topical here, so I created
simple 'placeholder' classes for 'CPoint' and 'CRect' in
this example. I also did not check the coordinate
arithmetic thoroughly. You'll have to decide what
makes one 'CPoint' value less than another, the same for
'CRect'; I just made it up as I went along. :)
I also reformatted things a bit to make it easier for
me to work with.

Anyway, this should get you started (and I suspect
others will jump in with corrections and ideas as well;
I'm not convinced this design is optimal for what
you're doing:

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <ostream>
#include <string>

class CPoint
{
public:
friend bool operator<(const CPoint& lhs, const CPoint& rhs)
{
return (lhs.x < rhs.x) || (lhs.y < rhs.y);
}

friend bool operator >=(const CPoint& lhs, const CPoint& rhs)
{
return !(lhs < rhs);
}

friend std::eek:stream& operator<<(std::eek:stream& os, const CPoint& p)
{
return os << '('
<< std::setw(2) << p.x
<< ", "
<< std::setw(2) << p.y
<< ')';
}

CPoint(long xx = 0, long yy = 0) : x(xx), y(yy)
{
}

private:
long x;
long y;
};

class CRect
{
friend bool operator<(const CRect& lhs, const CRect& rhs)
{
return lhs.topleft < rhs.topleft;
}

public:
CRect(long x, long y, long width, long height)
: topleft(x, y), bottomright(x + width, y + height)
{
}

bool PtInRect(const CPoint& p) const
{
return p >= topleft && p < bottomright;
}

private:
CPoint topleft;
CPoint bottomright;
};

class GISCode
{
friend bool operator<(const GISCode&, const GISCode&);

public:
GISCode(const std::string& c = "") : Code(c)
{
}

operator std::string() const; // get code
const std::string GetCode() const
{
return Code;
}

// Equality Operations (generated)
bool operator==(const GISCode&) const;
bool operator!=(const GISCode&) const;

// Exception class(es)
class CodeError : public std::logic_error
{
public:
CodeError(const std::string& = "");
const char* what() const;
private:
const std::string Code;
const std::string ErrMsg;
};

private:
void CheckCode(const std::string&) const;
std::string Code;
};

// Function object for determining is a point in Rect?
class PointInRect
{
public:
PointInRect(const CPoint& pp) : p(pp) {}
bool operator()(const std::pair<CRect, GISCode>& r)
{
return r.first.PtInRect(p);
}

private:
const CPoint p;
};

class CTehranCityView
{
public:
CTehranCityView()
{
m[CRect( 5, 0, 15, 10)] = GISCode("ABC");
m[CRect(20, 0, 12, 10)] = GISCode("DEF");
m[CRect( 0, 10, 20, 15)] = GISCode("GHI");
}

void OnLButtonDblClk(unsigned int nFlags, const CPoint& point)
{
std::map<CRect, GISCode>::const_iterator it =
std::find_if(m.begin(), m.end(), PointInRect(point));

std::cout << "Point " << point << ": ";

std::cout << "Code ";

if(it == m.end())
std::cout << "not found\n";
else
{
std::cout << it->second.GetCode() << '\n';
}
}

private:
std::map<CRect, GISCode> m;
};

int main()
{
std::cout << "m[CRect( 5, 0, 15, 10)] = GISCode(\"ABC\");\n";
std::cout << "m[CRect(20, 0, 12, 10)] = GISCode(\"DEF\");\n";
std::cout << "m[CRect( 0, 10, 20, 15)] = GISCode(\"GHI\");\n";

CTehranCityView cv;
long x = 0;
long y = 0;

while(x < 36)
{
while(y < 36)
{
cv.OnLButtonDblClk(0, CPoint( x, y));
y += 5;
}

x += 5;
y = 0;
}

return 0;
}


Output:

m[CRect( 5, 0, 15, 10)] = GISCode("ABC");
m[CRect(20, 0, 12, 10)] = GISCode("DEF");
m[CRect( 0, 10, 20, 15)] = GISCode("GHI");
Point ( 0, 0): Code not found
Point ( 0, 5): Code not found
Point ( 0, 10): Code GHI
Point ( 0, 15): Code GHI
Point ( 0, 20): Code GHI
Point ( 0, 25): Code GHI
Point ( 0, 30): Code GHI
Point ( 0, 35): Code GHI
Point ( 5, 0): Code ABC
Point ( 5, 5): Code ABC
Point ( 5, 10): Code GHI
Point ( 5, 15): Code GHI
Point ( 5, 20): Code GHI
Point ( 5, 25): Code GHI
Point ( 5, 30): Code GHI
Point ( 5, 35): Code GHI
Point (10, 0): Code ABC
Point (10, 5): Code ABC
Point (10, 10): Code GHI
Point (10, 15): Code GHI
Point (10, 20): Code GHI
Point (10, 25): Code GHI
Point (10, 30): Code GHI
Point (10, 35): Code GHI
Point (15, 0): Code ABC
Point (15, 5): Code ABC
Point (15, 10): Code GHI
Point (15, 15): Code GHI
Point (15, 20): Code GHI
Point (15, 25): Code GHI
Point (15, 30): Code GHI
Point (15, 35): Code GHI
Point (20, 0): Code ABC
Point (20, 5): Code ABC
Point (20, 10): Code GHI
Point (20, 15): Code GHI
Point (20, 20): Code GHI
Point (20, 25): Code DEF
Point (20, 30): Code DEF
Point (20, 35): Code DEF
Point (25, 0): Code ABC
Point (25, 5): Code ABC
Point (25, 10): Code GHI
Point (25, 15): Code GHI
Point (25, 20): Code GHI
Point (25, 25): Code DEF
Point (25, 30): Code DEF
Point (25, 35): Code DEF
Point (30, 0): Code ABC
Point (30, 5): Code ABC
Point (30, 10): Code GHI
Point (30, 15): Code GHI
Point (30, 20): Code GHI
Point (30, 25): Code DEF
Point (30, 30): Code DEF
Point (30, 35): Code DEF
Point (35, 0): Code ABC
Point (35, 5): Code ABC
Point (35, 10): Code GHI
Point (35, 15): Code GHI
Point (35, 20): Code GHI
Point (35, 25): Code not found
Point (35, 30): Code not found
Point (35, 35): Code not found


-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top