CheetahBongos
CheetahBongos

Reputation: 197

Code checking the result of std::unordered_set::find won't compile

I am writing a program to determine whether all characters in a string are unique or not. I am trying to do this using an unordered_set. Here is my code:

#include <iostream>
#include <unordered_set>
#include <string>

using namespace std;

bool uniqueChars(string word) {

    unordered_set<char> set;

    for (int i = 0; i < word.length(); i++) {
        auto character = set.find(word[i]);

        // if word[i] is found in set then not all chars are unique
        if (character == word[i]) {
            return false;
        }
        //else add word[i] to set
        else {
            set.insert(word[i]);
        }
    }
    return true;
}

int main() {

    string word;
    getline(cin, word);

    bool result = uniqueChars(word);
    return 0;
}

It is giving me this error:

|15|error: no match for 'operator==' (operand types are 'std::__detail::_Node_iterator' and 'char')|

I believe that means that character is not comparable to word[i], but I'm not sure.

How do I make this work?

Upvotes: 2

Views: 1454

Answers (3)

user2736738
user2736738

Reputation: 30926

*character == word[i] 

( This is the way to access the characters but it is not needed and it should be guided by a check whether it points to the past to the last element)

The *charcater is basically referencing the already inserted charcater.

  if(character != set1.end() )
     return false; // as we are sure  that it is not unique character string

You have to dereference it. but in that case you also need to do the whether it return iterator pointing to `set::end``.

By the way there is a really a simple way to do what you are trying to do.

bool uniqueChars(string word) {

    unordered_set<char> set1;

    for (int i = 0; i < word.length(); i++) 
        auto character = set1.insert(word[i]);

    return set1.size()==word.length();
}

"set" is a key word in c++

Upvotes: 0

Potatoswatter
Potatoswatter

Reputation: 137780

Take advantage of the return value of insert. It tells you whether a duplicate was found during insertion (in which case nothing is inserted).

bool uniqueChars(string word) {
    unordered_set<char> set;
    for ( char c : word ) {
        if ( ! set.insert( c ).second ) {
            return false; // set didn't insert c because of a duplicate.
        }
    }
    return true; // No duplicates.
}

However, this isn't as efficient as it might look. unordered_set is a heap-based hash table and its implementation is fairly heavyweight. A lightweight bit-vector works well for classifying characters.

#include <bitset>

constexpr int char_values = numeric_limits< char >::max()
                          - numeric_limits< char >::min() + 1;

bool uniqueChars(string word) {
    bitset< char_values > set;

    for ( char c : word ) {
        int value_index = c - numeric_limits< char >::min();

        if ( set[ value_index ] ) {
            return false;
        } else {
            set[ value_index ] = true;
        }
    }
    return true; // No duplicates.
}

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172894

Note that std::unordered_set::find returns an iterator, not the element. It can't be compared to the element directly.

You could check whether the element was found or not by comparing the iterator with std::unordered_set::end. e.g.

auto character = set.find(word[i]);

// if word[i] is found in set then not all chars are unique
if (character != set.end()) {
    return false;
}
//else add word[i] to set
else {
    set.insert(word[i]);
}

BTW: Better not to use set as the name of variable, which is the name of another STL container.

Upvotes: 1

Related Questions