条款35-实现简单的忽略大小写的字符串比较

方法一,mismatch()

/**
 * @brief 忽略大小写比较字符.
 * @param c1 字符 c1. 
 * @param c2 字符 c2.
 * @return int 若 c1 < c2, 则返回 -1; 若 c1 == c2, 则返回 0; 若 c1 > c2, 则返回 1.
 */
int ciCharCompare(char c1, char c2)
{
    // tolower() 的参数和返回值的类型是 int, 除非这个 int 是 EOF,
    // 否则它的值必须能表现为一个 unsigned char.
    // 在 C 和 C++ 中, char 可能或不可能是有符号的, 当 char 有符号时,
    // 唯一确认它的值可以表现为 unsigned char 的方式就是在调用 tolower() 之前
    // 转换一下.
    int lc1 = tolower(static_cast<unsigned char>(c1));
    int lc2 = tolower(static_cast<unsigned char>(c2));

    if (lc1 < lc2)
    {
        return -1;
    }
    if (lc1 > lc2)
    {
        return 1;
    }

    return 0;
}

int ciStringCompareImpl(const string &s1, const string &s2)
{
    // PSCI = "a pair of string::const_iterator".
    typedef pair<string::const_iterator, string::const_iterator> PSCI;

    // mismatch() 算法返回一对迭代器, 表示了区间中第一个对应的字符不相同的位置.
    PSCI p = mismatch(s1.begin(), s1.end(),
                      s2.begin(),
                      not2(ptr_fun(ciCharCompare)));

    // 如果为真.
    if (p.first == s1.end())
    {
        // s1 等于 s2.
        if (p.second == s2.end())
        {
            return 0;
        }
        // 或者 s1 比 s2 短.
        else
        {
            return -1;
        }
    }

    // 两个字符串的关系和不匹配的字符一样.
    return ciCharCompare(*p.first, *p.second);
}

int ciStringCompare(const string &s1, const string &s2)
{
    if (s1.size() <= s2.size())
    {
        return ciStringComparelmpl(s1, s2);
    }
    else
    {
        return -ciStringComparelmpl(s2, s1);
    }
}

方法二,lexicographical_compare()

将字符串比较工作交给 STL 中名字第二长的算法——lexicographical_compare(),为其提供一个判断式接口比较函数 ciCharLess()

lexicographical_campare()strcmp() 的泛型版本,其对任何类型的值的区间都起作用,可以传入一个决定两个值是否满足一个用户定义标准的二元判断式。

bool ciCharLess(char c1, char c2)
{
    return tolower(static_cast<unsigned char>(c1)) <
           tolower(static_cast<unsigned char>(c2));
}

bool ciStringCompare(const string &s1, const string &s2)
{
    return lexicographical_compare(s1.begin(), s1.end(),
                                   s2.begin(), s2.end(),
                                   ciCharLess);
}

方法三,strcmp()

牺牲移植性,不关心国际化,取而代之,将两个字符串都转换为 const char* 指针,然后对指针使用 strcmp()

int ciStringCompare(const string &s1, const string &s2)
{
    return strcmp(s1.c_str(), s2.c_str());
}

posted @ 2021-02-05 20:41  田世豪  阅读(177)  评论(0编辑  收藏  举报