Please Help: problem using char[9] as key type of map

C

Charlie

Dear all,

I am stuck on this problem, couldn't find an answer on any C++ book in
the bookshop.

Following is a cut of my program, and its error message:
============================================
280 map<char[9],vector<int> > _dict;
281 char* op_addr = op.get_address();
282 int op_time = op.get_time_stamp();
283 _dict[op_addr].push_back(op_time);
==========================================

class.cc:283: no match for `std::map<char[9], std::vector<int,
std::allocator<int> >, std::less<char[9]>,
std::allocator<std::pair<const
char[9], std::vector<int, std::allocator<int> > > > >& [char*&]'
operator
/usr/include/c++/3.2.2/bits/stl_map.h:221: candidates are: _Tp&
std::map<_Key,
_Tp, _Compare, _Alloc>::eek:perator[](const _Key&) [with _Key =
char[9], _Tp =
std::vector<int, std::allocator<int> >, _Compare =
std::less<char[9]>,
_Alloc = std::allocator<std::pair<const char[9], std::vector<int,
std::allocator<int> > > >]

=============================================

I wrote a small test program, to represent this problem, using char[]
as key type for a map. But it always fails to compile. I really don't
know how to make this char array to work. The reason I have to use
char[] in stread of stl::string, because it's primitive type, save lots
of memory, and also can help the process to give memory back to OS.
(input file is about 6Gb)

#include <iostream>
#include <map>

int main()
{
typedef std::map<char[9],int > DictType;
DictType _dict;

char _addr[9] = "12345678";
_dict.insert( DictType::value_type(_addr, 3) );
std::cout<<_dict[_addr]<<std::endl;

return 0;
}

It fails to compile, with following error message:

[root@localhost Trace_ana_stack_12May]# g++ -o try_char_map.exe
try_char_map.cc
/usr/include/c++/3.2.2/bits/stl_pair.h: In constructor `std::pair<_T1,
_T2>::pair(const _T1&, const _T2&) [with _T1 = const char[9], _T2 =
int]':
try_char_map.cc:10: instantiated from here
/usr/include/c++/3.2.2/bits/stl_pair.h:84: ISO C++ forbids assignment
of arrays

=========================================

I am really got no idea. Any help or comment is highly appreciate!

Many thanks!
Charlie
 
O

Old Wolf

Charlie said:
Dear all,

I am stuck on this problem, couldn't find an answer on any
C++ book in the bookshop.

Following is a cut of my program, and its error message:
============================================
280 map<char[9],vector<int> > _dict;

You can't use an array in a standard container.

You could use a std::string, or a std::vector<char>, or
boost::array<>. Or you could wrap your array:

struct char9
{
char ch[9];
bool operator<(char9 const &c);
};
 
L

Larry I Smith

Charlie said:
Dear all,

I am stuck on this problem, couldn't find an answer on any C++ book in
the bookshop.

Following is a cut of my program, and its error message:
============================================
280 map<char[9],vector<int> > _dict;
281 char* op_addr = op.get_address();
282 int op_time = op.get_time_stamp();
283 _dict[op_addr].push_back(op_time);
==========================================

class.cc:283: no match for `std::map<char[9], std::vector<int,
std::allocator<int> >, std::less<char[9]>,
std::allocator<std::pair<const
char[9], std::vector<int, std::allocator<int> > > > >& [char*&]'
operator
/usr/include/c++/3.2.2/bits/stl_map.h:221: candidates are: _Tp&
std::map<_Key,
_Tp, _Compare, _Alloc>::eek:perator[](const _Key&) [with _Key =
char[9], _Tp =
std::vector<int, std::allocator<int> >, _Compare =
std::less<char[9]>,
_Alloc = std::allocator<std::pair<const char[9], std::vector<int,
std::allocator<int> > > >]

=============================================

I wrote a small test program, to represent this problem, using char[]
as key type for a map. But it always fails to compile. I really don't
know how to make this char array to work. The reason I have to use
char[] in stread of stl::string, because it's primitive type, save lots
of memory, and also can help the process to give memory back to OS.
(input file is about 6Gb)

#include <iostream>
#include <map>

int main()
{
typedef std::map<char[9],int > DictType;
DictType _dict;

char _addr[9] = "12345678";
_dict.insert( DictType::value_type(_addr, 3) );
std::cout<<_dict[_addr]<<std::endl;

return 0;
}

It fails to compile, with following error message:

[root@localhost Trace_ana_stack_12May]# g++ -o try_char_map.exe
try_char_map.cc
/usr/include/c++/3.2.2/bits/stl_pair.h: In constructor `std::pair<_T1,
_T2>::pair(const _T1&, const _T2&) [with _T1 = const char[9], _T2 =
int]':
try_char_map.cc:10: instantiated from here
/usr/include/c++/3.2.2/bits/stl_pair.h:84: ISO C++ forbids assignment
of arrays

=========================================

I am really got no idea. Any help or comment is highly appreciate!

Many thanks!
Charlie

It'll be tough to get 6GB of data into a 'map' unless your
machine has a huge amount of RAM.

As 'Old Wolf' said, you can't use a char[] as a map key.
You can create a simple class to wrap you char[] so that
it can be used in a map or set. Below is a simple example
to get you started.

#include <iostream>
#include <cstring>
#include <map>

struct KEY9
{
char val[9];

KEY9()
{
std::memset(val, '\0', 9);
}

KEY9(const KEY9& oth)
{
std::memmove(val, oth.val, 9);
}

KEY9(const char * str)
{
std::memset(val, '\0', 9);
if (str)
{
strncpy(val, str, 8);
}
}

// required for 'map', 'set', etc
bool operator<(const KEY9& oth) const
{
return std::strcmp(val , oth.val) < 0;
}
};

int main()
{
typedef std::map<KEY9, int> DictType;
DictType dict;

KEY9 addr1("12345678");
KEY9 addr2("hello");

dict.insert( DictType::value_type(addr1, 3) );
dict.insert( DictType::value_type(addr2, 4) );

std::cout << addr1.val << ": " << dict[addr1] << std::endl;
std::cout << addr2.val << ": " << dict[addr2] << std::endl;

return 0;
}

Regards,
Larry
 
C

Charlie

Dear Larry,

Thank you sooo much for kindly providing such a nice example! It helped
me a lot! With your example, I can now get this problem successfully
solved!

Best regards,
Charlie
 
O

Old Wolf

Larry said:
struct KEY9
{
char val[9];
KEY9()
{
std::memset(val, '\0', 9);
}
KEY9(const KEY9& oth)
{
std::memmove(val, oth.val, 9);
}

Good answer. Is there any reason for preferring these
functions to:

std::fill_n(val, 9, 0)
std::copy(oth.val, oth.val + 9, val);

? BTW I think memcpy can be used rather than memmove, as val
and oth.val cannot overlap (you can't copy construct an object
from itself).
 
L

Larry I Smith

Old said:
Larry I Smith wrote:

struct KEY9
{
char val[9];
KEY9()
{
std::memset(val, '\0', 9);
}
KEY9(const KEY9& oth)
{
std::memmove(val, oth.val, 9);
}


Good answer. Is there any reason for preferring these
functions to:

std::fill_n(val, 9, 0)
std::copy(oth.val, oth.val + 9, val);

? BTW I think memcpy can be used rather than memmove, as val
and oth.val cannot overlap (you can't copy construct an object
from itself).

25 years of paranoid defensive programming, and performance
considerations. Often, the mem*() functions are implmented
in Assembly Language; this can be a major performance
consideration if the OP plans to use many KEY9 objects
(thousands in a container perhaps). Yes memcpy() is OK
in the constructors, but I've been conditioned by my
company's 'technical standards' to always use memmove().

Regards,
Larry
 
R

Ron Natalie

Old said:
Larry I Smith wrote:

struct KEY9
{
char val[9];
KEY9()
{
std::memset(val, '\0', 9);
}
KEY9(const KEY9& oth)
{
std::memmove(val, oth.val, 9);
}


Good answer. Is there any reason for preferring these
functions to:

std::fill_n(val, 9, 0)
std::copy(oth.val, oth.val + 9, val);
Yes, it's much more likely that memset and related functions
are specialized for char then standard algorithms.
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top