Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

ATL and <map>

Posted on 2001-06-15
13
Medium Priority
?
218 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
  • 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
Technology Partners: 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 600 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

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

Question has a verified solution.

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

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

773 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