1

I am writing c++ to sort a string vector. The string should be sorted by its length. If the lengths are the same, sorting by its lexicographical order: eg: abc < abd Here is my code:

static bool sort_find(string& a, string& b){
         if(a.size() < b.size()){
             return true;
         }
         else if(a.size() > b.size()){
             return false;
         }
         else{
             for(int i=0;i<a.size();i++){
                if(a[i] ==  b[i] )
                  continue;
                 else if(a[i] < b[i]){
                    return true;
                  }
                 else{
                   return false;
                }
             }
             return true;
         }
     }

int main(){

 string array[13]={"m","mo","moc","moch","mocha","l","la","lat","latt","latte","c","ca","cat"};

 vector<string> svector(array,array+13);
 sort(svector.begin(),svector.end(),sort_find);
 return 0;
}

The output of this code is [c, l, m, ca, la, moch, mo, cat, lat, moc, latt, mocha, latte] The output does not make sense to me.

Everyone's help is welcome!!

Thanks!

0

1 Answer 1

1

At first, I thought it was fine. It worked for me. But that was pure luck.

If you look up std::sort, and follow the link for the requirements on the comparison function to http://en.cppreference.com/w/cpp/concept/Compare you will find that it must be a strict weak ordering, including the requirement that

For all a, comp(a,a)==false

You return true if both strings are the same. This does not make sense, as you are really defining the less than operator. This leads to unexpected behavior with std algorithms and data structures which expect a strict weak ordering.

In order to fix it, I would recommend that if the lengths are the same, you simply return a<b, as std::string already has lexicographical comparison.

bool compare_length_then_string_lt(const string& a, const string& b) {
    if (a.size() < b.size())
        return true;
    else if (a.size() > b.size())
        return false;
    else
        return a < b;
}

std::sort(svector.begin(), svector.end(), compare_length_then_string_lt);

But I almost forgot. When combining multiple different ways to compare two structs, you can often use std::tuple or std::tie, which already know how to chain the comparisons together correctly. You just tell them what components to compare in what order, and they take care of the rest:

std::sort(svector.begin(), svector.end(),
    // lambda notation
    [](const std::string &lhs, const std::string &rhs) {
        // comparator body
        return std::make_tuple(lhs.size(), lhs) < std::make_tuple(rhs.size(), rhs);
    }
);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.