【C++】STL 算法 ⑦ ( 二元谓词使用场景 - 大小写不敏感 set 集合 | tolower 函数 - 将字符转为小写字母 | 基于 tolower 实现大小写不敏感的比较函数对象 )

C/C++
169
0
0
2024-03-24
文章目录
  • 一、二元谓词使用场景 - 大小写不敏感 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 . . .

在这里插入图片描述