Dante May Code
Dante May Code

Reputation: 11247

How to get char[] to work with std::map

EDIT after answered:

< should be provided for std::map. For more information about best practice, go for James McNellis's answer.

The code included in this question is poorly written. It is just because I am playing with SPOJ and the input data is strictly valid. The std::string approach is what I chose at first, but it turned out to be not fast enough.

Thank you.


I know I cannot use char[] directly with map, such as map<char[], int>. Thus I put it in a class. But it still can go through compilation. How to deal with that?


#include <stdio.h>
#include <map>

using namespace std;

class id {
public:
    char v [30];
};

int main () {
    map<id, int> m;
    id a;
    while (gets(a.v)) {
        m[a]++;
    }
    return 0;
}

/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = id]’:
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_map.h:418:   instantiated from ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = id, _Tp = int, _Compare = std::less<id>, _Alloc = std::allocator<std::pair<const id, int> >]’
prog.cpp:15:   instantiated from here
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’

It seems it has something to do with comparison, but I am still in the dark.

Upvotes: 1

Views: 390

Answers (3)

James McNellis
James McNellis

Reputation: 355039

First things first: never, ever use gets. It cannot be used safely and any program that uses it has a security vulnerability. There is no way to limit the number of characters that gets can write to the buffer that you provide it, so there is no way to prevent a buffer overflow. If you do need to use the C I/O library, you should use fgets instead, which allows you to specify the maximum number of characters to be read.

The reason that you are seeing this error is that the key type that you use must be comparable somehow. By default std::map uses operator<, which you do not define for id, hence the compilation error. You either need to define operator< to compare two id objects or you need to write a comparator functor that can be used to compare the two objects. Regardless which you choose, the comparator must provide a strict-weak ordering.

Since you are programming in C++, the ideal solution here is to use idiomatic C++:

std::map<std::string, int> m;
std::string s;
while (std::cin >> s) {
    m[s]++;
}

std::string already provides operator< that provides a lexicographic ordering, so you don't need to define a comparator yourself.

Upvotes: 6

i_am_jorf
i_am_jorf

Reputation: 54600

In order to insert into the map, the map needs to be able to compare id's. You haven't provided an implementation of operator< that it can use. You have two options:

  1. Provide one, example given by another answer here.
  2. Use std::string instead.

I think you should use std::string. You can use the .c_str() method to convert it to a char array when you need to.

Upvotes: 0

GWW
GWW

Reputation: 44093

You need to implement the < operator

class id {
public:
    char v [30];
    bool operator<(const id &rhs) const{
        return strcmp(v,rhs.v) < 0;
    }
};

EDIT: As a side note your code is a very poor way of doing things. See some of the answers for an explanation why.

Upvotes: 3

Related Questions