Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Critiques (even pedantic ones) are welcome.

bool unique_chars(std::string &s) {
    if (s.length()>256) return false;
    std::bitset<256> bs;
    for (auto &c:s) {
        if (bs.test(c)) return false;
        bs.set(c);
    }
    return true;
}
share|improve this question
 
Is there more code to show (such as with testing the function)? It'll be easier to review as we can see how it works. –  Jamal yesterday
1  
I know. I've already tested it myself. I wanted to see if the OP had done some other tests. –  Jamal yesterday
2  
I'm curious why the len <= 256 restriction. I'm assuming it's so that your bitset can hold all possibilities (if there's at most 256 characters, there are at most 256 unique characters). You can pretty safely ease this restriction though since std::string is extremely likely to only hold 256 unique characters (since it's std::basic_string<char> and char is almost always 8 bits). –  Corbin yesterday
1  
@Corbin I think it's an early return: if the string is long then he knows (without spending further time testing it) that it must contain duplicated characters. –  ChrisW 18 hours ago
1  
@WayneConrad According to cplusplus.com/reference/string/string/length it's O(1) in C++ 11; it inevitably makes things a little slower for small strings. I worried about whether taking a non-const reference to the contents of a non-const string might be expensive; but maybe the compiler+library is smart enough to defer copying a shared/reference-counted string content until/unless there's a write to the content (copy-on-write). –  ChrisW 17 hours ago
show 9 more comments

4 Answers

That's pretty good. It's short. The early returns communicate intent well, and since the function is short, they don't get lost. Formatting is good, and the variable names, although very short, are common abbreveviations that work well here.

I'd consider making the argument const, since it's not modified by the function.

I've been out of C++ a long time, so I might be missing something here, but I'd consider auto c:s instead of auto &c:s. I can't see a reason to work with a reference when a character is cheap to copy.

share|improve this answer
add comment

One theoretical place that this code might fail is when the string contains multibyte characters.

For example UTF-8 encoding is being used and string passed to the function is "€Abبώиב¥£€¢₡₢₣₤₥₦§₧₨₩₪₫₭₮漢Ä©óíßä" although no character is being repeated, the function will return true.

But handling this case is not straight forward at all, as standard library doesn't provide any way to iterate over actual characters in a string.

share|improve this answer
add comment

@Wayne Conrad has made some good points. I just have a few additional ones:

  • I'm not sure about checking against a maximum value, but I'll address it anyway.

    In case you'd like to change the default 256, consider having a template parameter. That way, the value can be changed at just one location. It'll also give more meaning to that value.

    template <std::size_t maxChars = 256>
    bool unique_chars(std::string &s) {
        if (s.length() > maxChars) return false;
        std::bitset<maxChars> bs;
    
        // ...
    }
    
  • To slightly add on to Wayne's point about const, make sure the argument is const& so that no unnecessary copying is done.

  • Consider renaming the function to something like areUniqueChars(). Otherwise, it may sound like it's returning the number of unique chars.

  • In C++, prefer to put unary operators (such as & and *) next to the type:

    std::string& s;
    

    for (auto& c : s) {}
    
share|improve this answer
add comment

Critiques (even pedantic ones) are welcome.

There's no 'functional specification' included with your question, there is just the code. You should include a functional specification, a.k.a. "the problem" to be solved, or "the requirements". Without one, we can see what the code does, but cannot assess whether what it does matches what it is required .

If the (missing) functional specification said, "string", then perhaps it doesn't mean only std::string ... for example, it might also mean std::wstring.

If so then your unique_chars should be a template function (in the same way that std::basic_string is a template class).

If you were working with very wide multi-byte characters (e.g. std::char32_t) you would prefer std::set or std::unordered_set (a hash set) instead of a std::bitset.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.