Solved

ATL and <map>

Posted on 2001-06-15
13
207 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
 
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.

758 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

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now