文章目录
- 一、二元谓词使用场景 - 大小写不敏感 set 集合
- 1、需求分析
- 2、tolower 函数 - 将字符转为小写字母
- 3、toupper 函数 - 将字符转为大写字母
- 4、基于 tolower 实现大小写不敏感的比较函数对象
- 二、代码示例 - 二元谓词使用场景
- 1、普通的 set 集合查找元素 - 大小写匹配查找成功
- 2、普通的 set 集合查找元素 - 大小写不匹配查找失败
- 3、设置二元谓词规则的 set 集合查找元素 - 大小写不不敏感集合
一、二元谓词使用场景 - 大小写不敏感 set 集合
1、需求分析
本篇博客中 , 实现一个 set 集合 , 存放 英文字母 组成的字符串 , 且 大小写不敏感 ;
实现的方法 : 自定义字符串 对比排序规则 , 先 将 字符串 都转为小写字母 , 然后进行对比 ;
2、tolower 函数 - 将字符转为小写字母
tolower 函数是 C / C++ 标准库 中的函数 , 其作用是 将 字符从 大写形式 转换为 小写形式 , 该函数定义在 C++ 头文件 的 <cctype> 中 或 C 语言头文件的 <ctype.h> 中 ;
- 如果传入的 字符 是 大写字母 , 将 该大写字母 转为小写字母 并返回 ;
- 如果传入的 字符 是 小写字母 , 将 该小写字母 直接返回 ;
tolower 函数原型如下 :
int tolower(int c);
- 参数解析 : 参数 c 表示字符的 int 类型的值 ;
- char -> int 类型转换 : 参数中使用了 int 类型值 , 一般情况下此处应该传入一个 char 类型的值 , 该 字符 会被隐式地转换为 int 类型 ;
- 传入的值需要 在 [ CHAR_MIN , CHAR_MAX ] 区间 中 , 或者 是 EOF ( -1 ) 值 ;
- 返回值解析 : 如果 参数 c 是 大写字母 , 则返回对应的小写字母 ; 否则 , 返回 c 字符本身 ; 返回值是 int 类型的 , 但通常可以安全地将其转换回 char 类型 ;
注意 : 为了保证 tolower 函数的行为 的 稳定性 , 建议 先将 char 类型的参数转换为 unsigned char , 然后 再传递给 tolower 函数 ; 运行该程序的平台可能是 Windows / Linux , Arm / 单片机 平台 , 如果 char 在指定的平台上 被当作负数处理 , 直接传递给 tolower 可能会导致未定义的行为 ;
代码示例 :
#include "iostream"
using namespace std;
#include <algorithm>
int main() {
string hello = "Hello, World!";
// 将字符串中的所有字符元素转为小写字母
transform(hello.begin(), hello.end(), hello.begin(), tolower);
cout << hello << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
hello, world! Press any key to continue . . .
3、toupper 函数 - 将字符转为大写字母
与 tolower 函数对象 相对的是 toupper 函数 , 可以将 字符 转为 大写形式 ;
toupper 函数原型如下 :
int toupper(int c);
- 参数解析 : 参数 c 表示字符的 int 类型的值 ;
- char -> int 类型转换 : 参数中使用了 int 类型值 , 一般情况下此处应该传入一个 char 类型的值 , 该 字符 会被隐式地转换为 int 类型 ;
- 传入的值需要在 [ CHAR_MIN , CHAR_MAX ] 区间 中 , 或者是 EOF ( -1 ) 值 ;
- 返回值解析 : 如果参数 c 是 小写字母 , 则返回对应的大写字母 ; 否则 , 返回 c 字符本身 ; 返回值是 int 类型的 , 但通常可以安全地将其转换回 char 类型 ;
代码示例 :
#include "iostream"
using namespace std;
#include <algorithm>
int main() {
string hello = "Hello, World!";
// 将字符串中的所有字符元素转为大写字母
transform(hello.begin(), hello.end(), hello.begin(), toupper);
cout << hello << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
HELLO, WORLD! Press any key to continue . . .
4、基于 tolower 实现大小写不敏感的比较函数对象
该 set 集合 的 比较函数 的 函数对象 , 是一个二元谓词 ,
重写的 函数调用操作符 函数如下 :
bool operator()(const string& str1, const string& str2)
接收 2 个 字符串 参数 ,
注意 : 比较的前提是 不能修改实参的值 , 这里重新创建 2 个字符串 , 用于 将 字符串转为 小节字母 并 进行比较 ;
首先 , 创建一个新的 字符串 对象 ;
// 创建字符串
string s1;
然后 , 根据 传入的 字符串参数大小 , 设置 新创建的字符串对象 ;
// 重新设置字符串大小
s1.resize(str1.size());
最后 , 调用 transform 算法 , 将 字符串 中的字符元素 , 都转为小写字母 ;
// 将字符串的所有元素都转换为小写元素
transform(str1.begin(), str1.end(), s1.begin(), tolower);
得到 全是 小写字母 的字符串 后 , 使用该 小写字母 字符串 与 另外一个参数 转成的 小写字母 字符串 进行对比 , 这样就实现了 大小写不敏感的 set 集合 ;
代码示例如下 :
#include <algorithm>
#include "functional"
/// <summary>
/// 二元谓词 大小写不敏感比较
/// </summary>
class Compare
{
public:
bool operator()(const string& str1, const string& str2) const
{
// 比较的前提是不能修改实参的值
// 这里重新创建 2 个字符串 , 用于进行比较
// 创建字符串
string s1;
// 重新设置字符串大小
s1.resize(str1.size());
// 将字符串的所有元素都转换为小写元素
transform(str1.begin(), str1.end(), s1.begin(), tolower); //预定义函数对象
string s2;
s2.resize(str2.size());
transform(str2.begin(), str2.end(), s2.begin(), tolower); //预定义函数对象
// 从小到大进行排序
return (s1 < s2);
}
};
二、代码示例 - 二元谓词使用场景
1、普通的 set 集合查找元素 - 大小写匹配查找成功
创建普通的 set 集合 , 并插入三个元素 ;
// 创建一个 set 集合容器
set<string> mySet;
// 向容器中插入元素
mySet.insert("b");
mySet.insert("a");
mySet.insert("c");
集合中的元素是
a b c
在集合中查找 字符串 " a " , 肯定能找到该元素 ;
代码示例 :
#include "iostream"
using namespace std;
#include <set>
#include <algorithm>
int main() {
// 创建一个 set 集合容器
set<string> mySet;
// 向容器中插入元素
mySet.insert("b");
mySet.insert("a");
mySet.insert("c");
// 向 foreach 循环中传入 Lambda 表达式
for_each(mySet.begin(), mySet.end(), [](string str) {
std::cout << str << " ";
});
cout << endl;
// 查找容器中的元素
set<string>::iterator it = mySet.find("a"); //find函数 默认 区分大小写
if (it != mySet.end()) {
cout << "找到了元素" << endl;
} else {
cout << "没有找到元素" << endl;
}
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
a b c 找到了元素 Press any key to continue . . .
2、普通的 set 集合查找元素 - 大小写不匹配查找失败
创建普通的 set 集合 , 并插入三个元素 ;
// 创建一个 set 集合容器
set<string> mySet;
// 向容器中插入元素
mySet.insert("b");
mySet.insert("a");
mySet.insert("c");
集合中的元素是
a b c
在集合中查找 字符串 " A " , 找不到该元素 ;
代码示例 :
#include "iostream"
using namespace std;
#include <set>
#include <algorithm>
int main() {
// 创建一个 set 集合容器
set<string> mySet;
// 向容器中插入元素
mySet.insert("b");
mySet.insert("a");
mySet.insert("c");
// 向 foreach 循环中传入 Lambda 表达式
for_each(mySet.begin(), mySet.end(), [](string str) {
std::cout << str << " ";
});
cout << endl;
// 查找容器中的元素
set<string>::iterator it = mySet.find("A"); //find函数 默认 区分大小写
if (it != mySet.end()) {
cout << "找到了元素" << endl;
} else {
cout << "没有找到元素" << endl;
}
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
a b c 没有找到元素 Press any key to continue . . .
3、设置二元谓词规则的 set 集合查找元素 - 大小写不不敏感集合
在下面的代码中 , 创建 set 集合时 , 指定了 集合元素的 排序规则 :
// 创建一个 set 集合容器
set<string, Compare> mySet;
该 Compare 排序规则 是一个 二元谓词 , 在排序时 , 将字符串先转为 小写字母 , 然后进行排序 ;
/// <summary>
/// 二元谓词 大小写不敏感比较
/// </summary>
class Compare
{
public:
bool operator()(const string& str1, const string& str2) const
{
// 比较的前提是不能修改实参的值
// 这里重新创建 2 个字符串 , 用于进行比较
// 创建字符串
string s1;
// 重新设置字符串大小
s1.resize(str1.size());
// 将字符串的所有元素都转换为小写元素
transform(str1.begin(), str1.end(), s1.begin(), tolower); //预定义函数对象
string s2;
s2.resize(str2.size());
transform(str2.begin(), str2.end(), s2.begin(), tolower); //预定义函数对象
// 从小到大进行排序
return (s1 < s2);
}
};
在排序时 , 大小写字母不敏感 , 即使是大写字母 " A " , 也会当做 " a " 进行排序 ;
查找元素时 , 查找 " A " 字符串 , 实际上查找的是 " a " 字符串 ;
使用 find 函数 查找元素时 , 可以找到 " A " 元素 ;
代码示例 :
#include "iostream"
using namespace std;
#include <set>
#include <algorithm>
#include "functional"
/// <summary>
/// 二元谓词 大小写不敏感比较
/// </summary>
class Compare
{
public:
bool operator()(const string& str1, const string& str2) const
{
// 比较的前提是不能修改实参的值
// 这里重新创建 2 个字符串 , 用于进行比较
// 创建字符串
string s1;
// 重新设置字符串大小
s1.resize(str1.size());
// 将字符串的所有元素都转换为小写元素
transform(str1.begin(), str1.end(), s1.begin(), tolower); //预定义函数对象
string s2;
s2.resize(str2.size());
transform(str2.begin(), str2.end(), s2.begin(), tolower); //预定义函数对象
// 从小到大进行排序
return (s1 < s2);
}
};
int main() {
// 创建一个 set 集合容器
set<string, Compare> mySet;
// 向容器中插入元素
mySet.insert("b");
mySet.insert("a");
mySet.insert("c");
// 向 foreach 循环中传入 Lambda 表达式
for_each(mySet.begin(), mySet.end(), [](string str) {
std::cout << str << " ";
});
cout << endl;
// 查找容器中的元素
set<string>::iterator it = mySet.find("A"); //find函数 默认 区分大小写
if (it != mySet.end()) {
cout << "找到了元素" << endl;
} else {
cout << "没有找到元素" << endl;
}
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
};
执行结果 :
a b c 找到了元素 Press any key to continue . . .