题目

编写程序,实现忽略英文字母大小写的字符串比较算法 iequals 与字典序比较函数 icompare。利用标准算法 std::equal 与 std::lexicographical_compare 配合 std::tolower,在不修改原字符串的前提下实现高性能比对,并把 icompare 封装为可直接传给 std::map 的自定义排序比较谓词。

输入格式:无需外部输入。

输出格式:输出多种大小写混杂字符串的判定与排序结果。

数据范围与约定:字符编码安全与 STL 算法适配。

思路与算法

1. unsigned char 类型转换防御
调用 std::tolower(c) 时必须先将 char 显式强转为 unsigned char,因为若 char 为有符号类型且包含负值字符时,直接传入标准 tolower 会引发未定义行为(断言崩溃或下标越界)。

2. 长度快速短路判定
判定两个字符串是否相等时,若 s1.size() != s2.size(),应立即返回 false,完全免除字符级别的遍历比对,大幅提升效率。

3. 字典序比较算法
std::lexicographical_compare 按照字典序从前向后逐字符对比,当遇到首个大小写转换后不相等的字符时决定相对次序,支持不同长度字符串的前缀比对。

完整程序

#include <iostream>
#include <string>
#include <string_view>
#include <algorithm>
#include <cctype>
#include <vector>
#include <map>

bool iequals(std::string_view a, std::string_view b) {
    if (a.size() != b.size()) return false;
    return std::equal(a.begin(), a.end(), b.begin(), [](char c1, char c2) {
        return std::tolower(static_cast<unsigned char>(c1)) ==
               std::tolower(static_cast<unsigned char>(c2));
    });
}

bool icompare(std::string_view a, std::string_view b) {
    return std::lexicographical_compare(
        a.begin(), a.end(), b.begin(), b.end(),
        [](char c1, char c2) {
            return std::tolower(static_cast<unsigned char>(c1)) <
                   std::tolower(static_cast<unsigned char>(c2));
        }
    );
}

struct ILess {
    bool operator()(const std::string& a, const std::string& b) const {
        return icompare(a, b);
    }
};

int main() {
    std::string s1 = "HelloWorld";
    std::string s2 = "helloworld";
    std::string s3 = "HELLOWORLD";

    std::cout << "s1 与 s2 忽略大小写比对: " << std::boolalpha << iequals(s1, s2) << "\n";
    std::cout << "s2 与 s3 忽略大小写比对: " << iequals(s2, s3) << "\n";
    std::cout << "s1 与 \"Hello\" 忽略大小写比对: " << iequals(s1, "Hello") << "\n\n";

    std::vector<std::string> words = {"banana", "Apple", "cherry", "avocado", "Banana"};
    std::sort(words.begin(), words.end(), icompare);

    std::cout << "忽略大小写字典序升序排序结果:\n";
    for (const auto& w : words) {
        std::cout << w << " ";
    }
    std::cout << "\n\n";

    std::map<std::string, int, ILess> scores;
    scores["Banana"] = 90;
    scores["apple"] = 80;
    scores["Cherry"] = 95;
    std::cout << "std::map + icompare 谓词按忽略大小写顺序遍历:\n";
    for (const auto& kv : scores) {
        std::cout << kv.first << ":" << kv.second << " ";
    }
    std::cout << "\n";

    return 0;
}

运行示例

输出:

s1 与 s2 忽略大小写比对: true
s2 与 s3 忽略大小写比对: true
s1 与 "Hello" 忽略大小写比对: false

忽略大小写字典序升序排序结果:
Apple avocado banana Banana cherry 

std::map + icompare 谓词按忽略大小写顺序遍历:
apple:80 Banana:90 Cherry:95