Solved

ATL and <map>

Posted on 2001-06-15
13
214 Views
Last Modified: 2013-12-14
Ive got problems trying to build a map<_TCHAR *, _TCHAR *>

First, I'll write my code:
     typedef map<_TCHAR *, _TCHAR *> type_Data;
     typedef type_Data::value_type vtItem;
   
      type_Data object;
      type_Data::iterator it;

if i build the map using variables, that is:
_TCHAR object_insert1[]="Item 1";
_TCHAR object_insert2[]="Item 2";
_TCHAR object_insert3[]="Item 3";
_TCHAR object_insert4[]="Item 4";
object.insert(vtItem(object_insert1,_T("VALUE_1")));
object.insert(vtItem(object_insert2,_T("VALUE_2")));
object.insert(vtItem(object_insert3,_T("VALUE_3")));
object.insert(vtItem(object_insert4,_T("VALUE_4")));

and i try to find an item using another variable,

_TCHAR object_find[]="Item 2";
it = object.find(object_find);

it doesn't find anything;

But if i build the map using strings without variables, that is:

object.insert(vtItem(_T("Item 1"),_T("VALUE_1")));
object.insert(vtItem(_T("Item 2"),_T("VALUE_2")));
object.insert(vtItem(_T("Item 3"),_T("VALUE_3")));
object.insert(vtItem(_T("Item 4"),_T("VALUE_4")));

 I find any of the items i'm looking for.

Does anyone know what's the problem?
0
Comment
Question by:Moony
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
13 Comments
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6194739
The problem is that you are storing pointers in the map, so the test made using find will do pointer comparison, hence typically, you will not find them.

You need something like this:

struct tstr_equal
{
  TSTR* mValue;
  tstr_equal(TSTR* s) : mValue(s) {}
  bool operator()(pair<const K, V> elem)
  {
     return wcscmp( elem->second, mValue ) == 0;
     // or however you compare TSTRs...
  }
};


then

it = find_if(object.begin(), object.end(),
             tstr_equal(object_find));

0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6195293
try typing your map

typedef map<string, string> type_Data;
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6195394
> try typing your map
> typedef map<string, string> type_Data;

wouldn't be very useful if unicode strings were being stored.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 9

Accepted Solution

by:
jasonclarke earned 200 total points
ID: 6195446
There were a few mistakes in the code I presented earlier, but here is a complete example that demonstrates the technique:

#pragma warning(disable:4786)

#include <tchar.h>
#include <map>
#include <algorithm>

using namespace std;

struct tstr_equal
{
 _TCHAR* mValue;

 tstr_equal(_TCHAR* s) : mValue(s) {}

 bool operator()(pair<_TCHAR *, _TCHAR *> elem)
 {
    return _tcscmp( elem.first, mValue ) == 0;
 }
};

int main()
{
    typedef map<_TCHAR *, _TCHAR *> type_Data;
    typedef type_Data::value_type vtItem;
   
    type_Data object;
    type_Data::iterator it;

    _TCHAR object_insert1[]="Item 1";
    _TCHAR object_insert2[]="Item 2";
    _TCHAR object_insert3[]="Item 3";
    _TCHAR object_insert4[]="Item 4";
    object.insert(vtItem(object_insert1,_T("VALUE_1")));
    object.insert(vtItem(object_insert2,_T("VALUE_2")));
    object.insert(vtItem(object_insert3,_T("VALUE_3")));
    object.insert(vtItem(object_insert4,_T("VALUE_4")));

    _TCHAR object_find[]="Item 2";
    it = find_if(object.begin(), object.end(), tstr_equal(object_find));

    _TCHAR* key = it->first;
    _TCHAR* value = it->second;

    return 0;
}
0
 

Author Comment

by:Moony
ID: 6195824
Wow! Your answer was perfect! Thank you very much!
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6195982
> wouldn't be very useful if unicode strings were being stored.

#ifdef _UNICODE
#define wstring string
#endif

no problem
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201461
> no problem

maybe, maybe not.  Many programs do not have the luxury of being able to operate entirely in one character set or another.  This kind of #define makes it impossible to use string for its plain ASCII text usage.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6201639
picky picky

typedef map<wstring, wstring> type_Data;

now we handle unicode strings

0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201702
> typedef map<wstring, wstring> type_Data;

still not really good enough, since the problem with TCHAR is that you don't know whether it will be wide until run-time, so you would have to do something like:

#ifdef _UNICODE
    typedef map<wstring, wstring> type_Data;
#else
    typedef map<string, string> type_Data;
#endif

Which, I agree does make life somewhat simpler.  Using pointers is probably more troublesome in general.  

But, having said that, it is possible to store TCHAR pointers directly in the map.  The use is just a bit more complicated, and somewhat less efficient.
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201707
> whether it will be wide until run-time

I meant compile time rather than run time....
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6201718
typedef basic_string<wchar_t> wstring;

and as I understand it wchar_t is a 'unsigned short' (see stddef.h) so by using wstring you know it is a wide string (unicode) - and since you solution used TCHAR then the same could be said about your own proposed solution
0
 
LVL 9

Expert Comment

by:jasonclarke
ID: 6201752
> and since you solution used TCHAR

not sure I understand your comment...

but the actual type of TCHAR depends on the system settings, i.e. if UNICODE, TCHAR = wchar_t, otherwise TCHAR = char.  

An advantage of using TCHARs directly is that maybe it makes it obvious that conversion *MAY* always be needed, it might be less easy to forget to do the conversion.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6202271
typedef basic_string<TCHAR> tstring;

its really not hard to apply the stl templates

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question