Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort a std::list with case sensitive elements?

This is my current code:

#include <list>
#include <string>
using std::string;
using std::list;

int main()
{
    list <string> list_;
    list_.push_back("C");
    list_.push_back("a");
    list_.push_back("b");

    list_.sort();
}

Does the sort() function sort the elements according to their character codes? I want the result here to be a b C after the sorting is done.

like image 907
cpx Avatar asked Apr 24 '26 11:04

cpx


1 Answers

Case-insensitive character comparisons are tricky if you want to support characters from other languages. That's why it's a good idea to do them in a locale-sensible manner:

struct char_iless 
: public std::binary_function<char, char, bool>
{
    std::locale loc;

    char_iless(std::locale const & loc=std::locale()) : loc(loc) 
    {
    }

    bool operator()(char a, char b) const
    {
        return std::tolower(a, loc) < std::tolower(b, loc);
    }
};

This is how you use this class to compare two chars:

char_iless('a', 'b', my_locale);

Just use std::locale() as my_locale if you want to use the one that's set as default.

If you can use Boost then there is am is_iless functor in the String Algorithms library which does the same thing.

Extending this from comparing chars to strings is easy thanks to std::lexicographical_compare:

struct str_iless 
: public std::binary_function<std::string, std::string, bool>
{
    std::locale loc;

    str_iless(std::locale const & loc=std::locale()) : loc(loc) 
    {
    }

    bool operator()(std::string const & a, std::string const & b) const
    {
        return std::lexicographical_compare(
            a.begin(), a.end(),
            b.begin(), b.end(),  
            char_iless(loc)
        );
    }
};

Now you have all that it's required to solve your problem:

int main()
{
    std::list<std::string> list;
    list.push_back("C");
    list.push_back("a");
    list.push_back("b");

    // Sort using default locale
    list.sort(str_iless());  

    // Sort using French locale 
    // (warning: this locale format string is MS specific)
    std::locale loc("French_France.1252");
    list.sort(str_iless(loc));
}
like image 61
Manuel Avatar answered Apr 26 '26 02:04

Manuel