I'm using the sort()
function in C++ to sort a vector of objects of type 'Game', which I defined myself. To do this, I am manually writing a function that will act in place of the operator<
, and which will be passed as the third parameter to the sort()
function. First, I compare based on scores. Then, if scores are tied, I compare based on team name.
What I need is a function alphabetical(string s1, string s2)
, that will return true if s1
would come before s2
in the dictionary. For example:
alphabetical("aardvark", "apple"); //true
alphabetical("balloon", "zebra"); //true
alphabetical("zebra", "apple"); //false
I also want it to return false if the strings are identical. Is there something in a library that I could use? Or, how would I write the function? I hope I'm coming across clearly.
std::string
implements a lexicographical less-than comparison operator itself, meaning that stringA < stringB
should usually do what you want. If you create a std::list<std::string> words
, sorting alphabetically will be as simple as words.sort();
Your custom Game
class could have its less-than comparison operator implemented simply as:
return (score < rhs.score) || (score == rhs.score && team < rhs.team)
It is worth noting that lexicographical sorting will not always be what a human would expect. Jeff Atwood goes into a discussion of so-called "natural sort order" versus lexicographical sort order in this post. His post also provides resources from which you will be able to find algorithms if such sorting is necessary to you.
A standard string comparison will work if your strings are all upper or lower. I believe it even works with character encodings that are not used anymore, such as EBSIDIC or whatever.
If you'll have mixed case then this does not work because 'A' is greater than 'z'. For this to work you'll want to use things like stricmp or whatever. You can also override char_traits for your basic_string to do insensitive comparison.
If you want to write the sort such that it places 'A' before 'a' or visa-versa but 'b' after 'a'...then you'll need to write your own. It should be fairly simple using the ASCII table, which most operating systems today use.
If you have to support languages other than English the problem actually becomes non-trivial.
If you're using std::string
s you can just use <
. But if you already have char*
, you don't want to (or can't) change that, and you want to avoid the overhead of converting to std::string
, then you can use std::lexicographical_compare()
.
Of course, in both cases, you probably want a case-insensitive comparison. Offhand I'm not sure what the right solution is for std::string
, probably something to do with char_traits
, but for lexicographical_compare()
you can provide a comparator:
bool alphabetical(const char *str1, const char *str2) {
return std::lexicographical_compare(str1, &str1[strlen(str1)], str2, &str2[strlen(str2)], [](char a, char b){
return tolower(a) < tolower(b);
});
}
来源:https://stackoverflow.com/questions/12361447/c-how-to-determine-whether-one-word-is-before-another-in-the-alphabet