【问题标题】:How to compare strings in c++ so as to sort them in a dictionary order? [closed]如何比较 C++ 中的字符串以便按字典顺序对它们进行排序? [关闭]
【发布时间】:2021-04-13 07:39:48
【问题描述】:

我想创建一个函数来按字典顺序比较两个字符串,以便我可以按“aa”

【问题讨论】:

  • 这能回答你的问题吗? Comparing strings lexicographically
  • 问题的标题有误,你想要一些特别的东西而不是字典比较
  • @AlessandroTeruzzi 它是按字典顺序排列的,只是没有按编码中的数值排序的单个字符。
  • @AlessandroTeruzzi,你能推荐一个更好的标题吗?
  • @harsh kapoor 我已经更新了答案,但如果我是你,我会花一两个小时编写我能想到的所有单元测试,以确保它的行为符合预期。

标签: c++ c++11 c++14


【解决方案1】:

你可能会这样做

auto compare_string = [](const auto& lhss, const auto& rhss){
    return std::lexicographical_compare(
        lhss.begin(), lhss.end(),
        rhss.begin(), rhss.end(),
        [](const auto& lhsc, const auto& rhsc){
            auto proj = [](char c){ return std::tuple(std::tolower(c), std::isupper(c)); };
            return proj(lhsc) < proj(rhsc);
        }
    );
});

Demo

【讨论】:

    【解决方案2】:

    你想要的字符串排序方式不是 std::string 默认实现的。但是,您可以传入您的 std::char_traits 模板参数并自定义排序。

    https://en.cppreference.com/w/cpp/string/char_traits

    这里有一个关于不区分大小写字符串实现的相当古老但仍然很有趣的讨论:http://www.gotw.ca/gotw/029.htm

    #include <string>
    #include <string_view>
    #include <iostream>
    #include <cctype>
    #include <cassert>
    
    
    struct special_char_traits : public std::char_traits<char> {
        static char to_upper(char ch) {
            return std::toupper((unsigned char) ch);
        }
        static bool eq(char c1, char c2) {
            return c1 == c2;
        }
        static bool lt(char c1, char c2) {
            if (c1 == c2)
                return false;
            if (to_upper(c1) == to_upper(c2))
                return !(c1 < c2);
            return c1 <  c2;
        }
        static int compare(const char* s1, const char* s2, std::size_t n) {
            while ( n-- != 0 ) {
                if ( lt(*s1,*s2)) return -1;
                if ( !lt(*s1,*s2)) return 1;
                ++s1; ++s2;
            }
            return 0;
        }
        static const char* find(const char* s, std::size_t n, char a) {
            while ( n-- != 0 ) 
            {
                if (*s == a)
                    return s;
                s++;
            }
            return nullptr;
         }
     };
    
    
     int main()
     {  
         typedef std::basic_string<char,special_char_traits> ss;
         //handle the case highligheted by Jarod42
         assert(!special_char_traits::lt('a','a'));
         assert(!special_char_traits::lt('A','A'));
         assert(special_char_traits::lt('a','A'));
         assert(!special_char_traits::lt('A','a'));
         assert(!special_char_traits::lt('b','A'));
         assert(special_char_traits::lt('A','b'));
    
         std::cout << (std::string("AA") < std::string("aa")) << " " << (ss("AA") < ss("aa")) << std::endl;    
     }
    

    仍有几个案例未经测试

    compare 函数将单个字符的比较委托给上面提供的 lt 函数。

    【讨论】:

    • 您的lt 方法似乎很奇怪...lt('a', 'a') 是错误的。您还依赖 ASCII ('A' &lt; 'a')(EBCDIC 有逆序)。
    【解决方案3】:
    std::string a = "A";
    std::string b = "B";
    if(a < b)
        // Do what you want.
    

    std::string 重载了 &lt; 运算符,这就是对它们进行排序所需的一切。

    另请参阅:Using the less than comparison operator for strings

    【讨论】:

    • 这不提供所需的顺序。
    【解决方案4】:

    只需创建一个以两个字符串作为输入的函数。在函数上创建 STL 集。插入两个字符串。它们现在在集合内按字典顺序排序。

    【讨论】:

    • 我认为 SO 提问者正在寻找可实施的解决方案。给出这些词通常没有帮助。这个答案的编程代码在哪里?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多