How to sort an array of string alphabetically (case sensitive, nonstandard collation)

前端 未结 6 1987
北荒
北荒 2020-12-02 19:15

I need a c language code to sort some strings and it should be case sensitive and for the same letter in upper- and lower-cases, the lower-case must come first

6条回答
  •  有刺的猬
    2020-12-02 19:54

    Here, if I got it right, you want something as I'd describe as follows:

    A case insensitive sort, where under tie, tiebreaker condition "lowercase comes first" is to be used.

    So it's like:

    1. earlier_letter_in_the_alphabet < later_letter_in_the_alphabet ignoring the case

    2. lowercase < uppercase

    3. shorter_word < wider_word
      • This wasn't mentioned, I borrowed it from the lexicographical order, the one in dictionaries
      • Can be utilized simply by taking '\0' as the lowest possible in comparisons

    Step 2 to be taken only if 1 didn't distinguish anything. Step 3 will already be checked with 1. All these are to be done letter-by-letter, meaning that you should switch to 2 as soon as you get a tie between corresponding characters, not just when the whole strings are on tie.


    Assuming that this was right, all we need to do now is to write a function that makes this comparison for us for any given two strings.

    #include   // for tolower and islower
    
    int my_character_compare(const char a, const char b)
    {
        int my_result;
    
        my_result = tolower(a) - tolower(b);
        // unless it is zero, my_result is definitely the result here
        // Note: if any one of them was 0, result will also properly favour that one
    
    
        if (my_result == 0 && a != b)
        // if (could not be distinguished with #1, but are different)
        {
            // means that they are case-insensitively same
            // but different...
            // means that one of them are lowercase, the other one is upper
            if (islower(a))
                return -1;  // favour a
            else
                return 1;   // favour b
        }
    
    
        // regardless if zero or not, my_result is definitely just the result
        return my_result;
    }
    
    int my_string_compare(const char * a, const char * b)
    {
        int my_result;
    
        my_result = my_character_compare(*a, *b);
        // unless it is zero, my_result is definitely the result here
    
        while (my_result == 0 && *a != 0)
        // current characters deemed to be same
        // if they are not both just 0 we will have to check the next ones
        {
            my_result = my_character_compare(*++a, *++b);
        }
    
        // whatever the my_result has been:
        //   whether it became != zero on the way and broke out of the loop
        //   or it is still zero, but we have also reached the end of the road/strings
        return my_result;
    }
    

    A compare function, by convention/rule, should return a negative value for favouring the first parameter to be in front, negative value for favouring the second parameter, zero if it cannot distinguish them. Just an additional information which you likely already know by the way you make use of strcmp.

    And that's it! Replacing that strcmp in your code with my_string_compare here, also putting up these definitions we've made on top should provide a correct result. Indeed it provides the expected result for the example input in question.

    One could shorten the definitions of course, I have made them long so that it will be easier to understand what's going on. For example, I could boil it all down to the following:

    #include 
    
    int my_string_compare(const char * a, const char * b)
    {
        int my_result;
    
        while (*a || *b)
        {
            if ((my_result = tolower(*a) - tolower(*b)))
                return my_result;
            if (*a != *b)
                return (islower(*a)) ? -1 : 1;
            a++;
            b++;
        }
    
        return 0;
    }
    

    Does essentially the same with the other one, you may use whichever you like; or even better, write one.

提交回复
热议问题