做网站什么系统简单,金华做网站建设公司,广西桂林阳朔旅游攻略必去景点,依安县建设网站C transform算法中toupper的使用
前言
用到这样一个函数#xff0c;将小写字符串转为大写。
// 一开始个人是这样写的#xff0c;这样没问题
std::transform(res.begin(), res.end(), res.begin(),[](unsigned char c) { return std::toupper(c); });
// 然后#xff0c;…C transform算法中toupper的使用
前言
用到这样一个函数将小写字符串转为大写。
// 一开始个人是这样写的这样没问题
std::transform(res.begin(), res.end(), res.begin(),[](unsigned char c) { return std::toupper(c); });
// 然后看到这样的写法
std::transform(res.begin(), res.end(), res.begin(),::toupper);
// 哎::toupper前面怎么没加std但加上后就会报错,正文为此问题的探究
// No matching function for call to transform candidate template ignored: couldnt infer template argument _UnaryOperation candidate function template not viable: requires 5 arguments, but 4 were provided正文
在C中std::toupper 函数有两种版本分别定义在头文件 cctype 中 全局函数版本 int toupper(int c);
// 同所有其他来自 cctype 的函数若参数值既不能表示为 unsigned char 又不等于 EOF 则 std::toupper 的行为未定义。为了以简单的 char 或 signed char 安全使用此函数首先要将参数转换为 unsigned char这是因为当字符的值是负数时传参给int会发生符号扩展使用 unsigned char 类型可以确保在字符转换时不会发生符号扩展从而得到正确的结果。
char my_toupper(char ch){return static_castchar(std::toupper(static_castunsigned char(ch)));
}
// 类似
std::string str_toupper(std::string s) {std::transform(s.begin(), s.end(), s.begin(), // static_castint(*)(int)(std::toupper) // 错误// [](int c){ return std::toupper(c); } // 错误// [](char c){ return std::toupper(c); } // 错误[](unsigned char c){ return std::toupper(c); } // 正确);return s;
}这是最常用的版本来自标准 C 库函数且同时位于全局和 std 名字空间接受一个整数参数 c返回将小写字母转换为大写字母后的整数值。如果 c 不是小写字母它将保持不变。 函数模板版本 template class CharT
CharT toupper( CharT ch, const std::locale loc );这个版本是函数模板接受一个字符 ch 和一个 std::locale 对象。它返回将字符 ch 在指定语言环境下转换为大写形式的结果。这个版本通常用于多语言环境下的字符转换。
在这两个版本中全局函数版本通常用得更广泛而函数模板版本用于特定的多语言环境需求。在实际编程中通常使用全局函数版本来进行字符大小写转换。
故当transform 函数也是一个模板函数的第四个参数是std::toupper的时候此时给定的 tolower 只是作为一个函数指针使用缺乏类型推导所需要的函数参数信息所以无法推导出函数的类型也就无法决定使用哪一个重载函数。故解决方法如下 指明函数类型 std::transform(res.begin(), res.end(), res.begin(),(int(*)(int))std::toupper);使用包装函数确定函数类型 int my_toupper( int c ) {
return toupper( c ); // 根据 c 的类型可以确定使用 toupper 的哪个重载函数。
}
// my_toupper 是非模版非重载函数避免了函数重载带来的类型解析问题。
transform( s.begin(), s.end(), s.begin(), my_toupper );调用全局下的tolower函数版本1和2都位于std命名空间下但版本1还位于全局空间下故可以直接指定命名空间为全局的那个tolower函数 std::transform(res.begin(), res.end(), res.begin(),::toupper);故tolower函数也是一样的。