azc
azc

Reputation: 11

Cannot make a <string, int> pair with char* as string in C++

I'm trying to have a map of <string, int>. I am trying to put individual characters of a given string as the key of the key value pair. However, I am running into this error:

Line 7: no matching function for call to 'std::unordered_map<std::__cxx11::basic_string<char>, int>::find(__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type&)'

This is my code:

int lengthOfLongestSubstring(string s) {
    unordered_map<string, int> map;
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        if (map.find(s[i]) == map.end()) {
            count++;
            map.insert(make_pair<string, int>(s[i], 1));
        } else {
            map.clear();
            count = 0;
        }
    }

    return count;
}

I think the error is because s[i] becomes a char* and so I cannot do make_pair since char* and string are different types.

I have tried to get around this by doing:

string temp(s[i]); // Try to create a string from the char* and pass it into the make_pair function

However, I still get the same error.

Upvotes: 1

Views: 1997

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 596397

std::string::operator[] returns a (reference to a) single char, not a char* pointer. You can't construct a std::string from just a char, which is why are you getting an error. To construct a std::string from a char, you need to use one of the following constructors:

basic_string(size_type count, CharT ch, const Allocator& alloc = Allocator());

basic_string(const CharT* s, size_type count, const Allocator& alloc = Allocator());

For example:

int lengthOfLongestSubstring(string s) {
    unordered_map<string, int> map;
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        string key(1, s[i]); // <-- here
        // or: string key(&s[i], 1);
        if (map.find(key) == map.end()) {
            count++;
            map.insert(make_pair(key, 1));
        } else {
            map.clear();
            count = 0;
        }
    }

    return count;
}

Otherwise, change your std::unordered_map keys to char instead, since that is what you are really using:

int lengthOfLongestSubstring(string s) {
    unordered_map<char, int> map; // <-- here
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        char key = s[i];
        if (map.find(key) == map.end()) {
            count++;
            map.insert(make_pair(key, 1));
        } else {
            map.clear();
            count = 0;
        }
    }

    return count;
}

However, you are not actually using the second value of the mapped pairs at all, so you don't really need the std::unordered_map at all, it is just wasted overhead. Consider using a std::set instead:

int lengthOfLongestSubstring(string s) {
    set<char> chars;
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        // set::insert() return true if inserted, false if duplicate
        if (chars.insert(s[i]).second) {
            count++;
        } else {
            chars.clear();
            count = 0;
        }
    }

    return count;
}

Upvotes: 0

songyuanyao
songyuanyao

Reputation: 172934

I think the error is because s[i] becomes a char* and so I cannot do make_pair since char* and string are different types.

No, what s[i] returns is just a single char (more precisely, a char& reference), which can't be converted to a std::string directly. To construct a std::string from a char, you need to use a different constructor of std::string, i.e:

basic_string( size_type count, CharT ch, const Allocator& alloc = Allocator() )

For example:

map.insert(make_pair<string, int>(string(1, s[i]), 1));

Or:

map.insert(make_pair<string, int>({1, s[i]}, 1));

Upvotes: 2

Related Questions