题目
编写程序,实现忽略英文字母大小写的字符串比较算法 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