小古银的官方网站(完整教程):http://www.xiaoguyin.com/
C++入门教程视频:https://www.bilibili.com/video/av20868986/
目录 函数类型 基础示例 1基础示例 2基础讲解 2基础示例 3基础讲解 3 补充知识(了解即可)
函数类型
函数实际上也是一个值,也就是说,函数可以用变量来保存,而这个变量的数据类型是std::function。std::function是一个类,它在functional标准库中。
假设要保存函数int myabs(int num);,那么就需要使用数据类型std::fuction<int(int)>,即在std::function的<>里面填返回值(参数类型),完整的赋值语句是std::function<int(int)> myfunc = myabs;。当然也可以用auto来声明变量:auto myfunc = myabs;。
简短的示例:
int myabs(int num); // 声明函数std::function<int(int)> myfunc = myabs; // 用变量myfunc保存myabs函数myabs(-1024); // 函数的调用myfunc(-2333); // 这时候myfunc也是函数,调用方法和上面myabs一样以下讲解函数类型的用途,即为什么要用函数类型。先看几个问题。
写一个函数,函数声明是这样的:unsigned int count_gu(std::u32string text);;功能是用来统计指定字符串中有多少个古字;函数有一个参数text,就是需要被统计的字符串;返回类型是unsigned int,代表字符串中有多少个古字。
基础示例 1 #include <iostream> // std::cout std::endl#include <string> // std::u32string// 以下是统计函数的使用说明// 功能: 统计指定字符串中有多少个古字// 参数: 需要被统计的字符串// 返回值: 字符串中古字的数量unsigned int count_gu(std::u32string text);int main(void){ // 统计字符串中一共有多少个古字 auto numofgu = count_gu(U"小古银小古银我是美美哒小古银"); std::cout << R"raw(字符串有多少个古字:)raw" << numofgu << std::endl; return 0;}unsigned int count_gu(std::u32string text){ // 遍历字符串中所有字符, 如果符合条件则统计 unsigned int count = 0; // 用来保存统计数量 for (auto ch : text) { if (ch == U'古') { ++count; } } // 返回统计数量 return count;}输出结果:
字符串有多少个古字:3再写一个函数,函数声明是这样的:unsigned int count_guyin(std::u32string text);;功能是用来统计古字和银字在指定字符串中一共有多少个;函数有一个参数text,就是需要被统计的字符串;返回类型是unsigned int,代表字符串中一共有多少个古字和银字。
基础示例 2 #include <iostream> // std::cout std::endl#include <string> // std::u32string// 以下是统计函数的使用说明// 功能: 统计指定字符串中一共有多少个古字和银字// 参数: 需要被统计的字符串// 返回值: 字符串中古字和银字的数量unsigned int count_guyin(std::u32string text);int main(void){ // 统计字符串中一共有多少个古字 auto numofguyin = count_guyin(U"小古银小古银我是美美哒小古银"); std::cout << R"raw(字符串有多少个古字和银字:)raw" << numofguyin << std::endl; return 0;}unsigned int count_guyin(std::u32string text){ // 遍历字符串中所有字符, 如果符合条件则统计 unsigned int count = 0; // 用来保存统计数量 for (auto ch : text) { if (ch == U'古' || ch == U'银') { ++count; } } // 返回统计数量 return count;}输出结果:
字符串有多少个古字和银字:6 基础讲解 2可以看出两份代码中,unsigned int count_gu(std::u32string text);和unsigned int count_guyin(std::u32string text);的函数定义除了if的判断不同,其他部分是一模一样的。既然两个函数的功能都是统计,而定义基本都是一样,那么就要考虑把它们统一成一个函数。
之前是因为值不同,所以可以用变量来作为函数参数来保存不同的值;而现在是不同的语句,可以考虑将语句写在函数里。上面说明过,函数也是一个值,不同的函数是不同的值,既然是值就可以用变量来保存。那么就可以将判断语句放到函数里,然后通过形式参数传到统计函数里。这时候就要考虑,这个用来判断的函数怎样写,同样也要考虑参数的类型是什么。
这个判断函数是用来放判断条件的。之前说过,判断就是一个运算,而运算结果是bool,那么这个判断函数的返回值就是bool。而需要判断的就是一个字符,那么形式参数的类型就是char32_t。这样,我们自己定义函数名isgu用来判断字符是不是古字,定义函数名isguyin用来判断字符是不是古字或者银字。这两个函数的函数声明如下:
bool isgu(char32_t ch);bool isguyin(char32_t ch);由于它们的返回值和参数类型都是一样的,那么它们都可以用类型std::function<bool(char32_t)>声明的变量来保存,例子如下:
std::function<bool(char32_t)> isgufunc = isgu;std::function<bool(char32_t)> isguyinfunc = isguyin;所以可以用数据类型std::function<bool(char32_t)>来作为统计函数的参数的数据类型。
基础示例 3那么将两个函数统一成一个函数就可以这样写:
#include <iostream> // std::cout std::endl#include <functional> // std::function#include <string> // std::u32string// 以下是统计函数的使用说明// 功能: 统计函数// 参数: 需要被统计的字符串// 参数: 统计函数需要的判断函数, 统计函数将会向判断函数传入每一个字符,// 然后统计函数会根据判断函数的返回值进行统计, 如果判断函数返回// true, 统计函数则会处理; 如果判断函数返回false, 统计函数则忽略// 返回值: 统计判断函数返回true的数量unsigned int count_if(std::u32string text, std::function<bool(char32_t)> pred);// 判断指定的UTF-32字符是不是古字// 参数: 需要判断的字符// 返回值: 如果指定字符是古字则返回true; 反之返回falsebool isgu(char32_t ch);// 判断指定的UTF-32字符是不是古字或者银字// 参数: 需要判断的字符// 返回值: 如果指定字符是古字或者银字则返回true; 反之返回falsebool isguyin(char32_t ch);int main(void){ // 统计字符串中一共有多少个古字 auto numofgu = count_if(U"小古银小古银我是美美哒小古银", isgu); // 统计字符串中一共有多少个古银这两个字 auto numofguyin = count_if(U"小古银小古银我是美美哒小古银", isguyin); // 输出 std::cout << R"raw(字符串有多少个古字:)raw" << numofgu << std::endl; std::cout << R"raw(字符串有多少个古字和银字:)raw" << numofguyin << std::endl; return 0;}unsigned int count_if(std::u32string text, std::function<bool(char32_t)> pred){ // 遍历字符串中所有字符, 如果符合条件则统计 unsigned int count = 0; // 用来保存统计数量 for (auto ch : text) { if (pred(ch)) { ++count; } } // 返回统计数量 return count;}bool isgu(char32_t ch){ return ch == U'古';}bool isguyin(char32_t ch){ return ch == U'古' || ch == U'银';}输出结果:
字符串有多少个古字:3字符串有多少个古字和银字:6 基础讲解 3先从设计函数的思维去看:函数count_if()用来统计符合条件的字符数量。然而函数count_if()只负责统计,它并不知道什么样的条件是符合的,他就把这个任务交给参数pred去负责,把每只字符都给pred()函数判断一下,只要pred()函数返回true,函数count_if()就认为是符合条件而去统计。那么函数count_if()就可以专心负责统计而不用理会细节。而参数pred就身负着判断是否符合条件的重任,它化身成为类型是std::function<bool(char32_t)>的函数,只为了完成判断每种不同条件的光荣使命。
再从调用函数的角度去玩:就是统计函数的使用说明。函数count_if()的第一个参数是需要被统计的字符串,而第二个参数是给函数count_if()判断用的,应该由调用者来定义什么字符是需要被统计的。我们需要统计有多少个古字,还有需要统计一共有多少个古字和银字,所以就写了两个判断函数isgu和isguyin,供统计函数判断使用。
补充知识(了解即可)std::function从C++11开始加入。