C++中一些方便的算法函数和吃不够的语法糖

前言

C++由于其复杂性,学习成本很高。但是作为接近底层的语言,学会之后能做的事情相当多,C++给了开发者极大的自由,只要符合规范就可以尽情的折腾,不过对于日常使用来说确实不太“方便”,特别是相比于Python、JS这类脚本语言,处理一些小问题时前奏太长,很多常用操作都需要自己造轮子,这一点在刷题时感觉很明显,C++一碰到字符串分析就“头大”,Python用一行搞定,用C++则需要N行。

变化

其实很多人对C++的认识还停留在 C++98 或者 C++03 版本,然而从 C++11 版本开始C++就发生了翻天覆地的变化,近期在使用的过程中发现C++也有很多方便的函数,越高的版本越方便,语法糖也越多,今天先总结几个,后续再补充吧。

优秀函数和语法糖

使用find系列实现trim函数

trim函数在很多语言中都是内置函数,可以去除收尾两端的空格,在C++中是没有trim函数的,需要自己实现一下,需要用到的工具函数有下面两个:

  • find_first_not_of:在字符串s中找到第一个不等于指定字符序列ACDE..的位置
  • find_last_not_of:在字符串s中找到最后一个不等于指定字符序列ACDE..的位置

find_first_not_of("hello world", "he") 指的就是找到第一个不等于 h 且不等于 e 字母的字符位置,要想去除字符串首尾空格就需要找到第一个不等于空格的位置,和最后一个不等于空格的位置,保留这两个位置中的部分即可,实现如下:

1
2
3
4
5
6
std::string& trim(std::string &s) {
if (s.empty()) return s;

s.erase(0, s.find_first_not_of(" "));
return s.erase(s.find_last_not_of(" ") + 1);
}

测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>
#include <iostream>
using namespace std;

std::string& trim(std::string &s) {
if (s.empty()) return s;

s.erase(0, s.find_first_not_of(" "));
return s.erase(s.find_last_not_of(" ") + 1);
}

int main() {
string s(" Hello world ");

cout << "before trim ==>" << s << "<<==" << endl;
cout << "after trim ==>" << trim(s) << "<<==" << endl;

return 0;
}

测试结果如下:

1
2
3
4
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ g++ stringtrim.cpp -o stringtrim
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ ./stringtrim
before trim ==> Hello world <<==
after trim ==>Hello world<<==

使用regex实现split函数

split 也是一个常用但C++不提供的函数,在C语言和早期的C++中一般通过 strtok 函数来实现,但是从 C++11 开始可以通过 regex 来实现,可以看下面这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <regex>
#include <string>
#include <iostream>
using namespace std;

int main() {
string s("c++11 test split");

regex reg(" "); // "\\s+" for blank
vector<string> v(sregex_token_iterator(s.begin(), s.end(), reg, -1), sregex_token_iterator());

for (auto str : v)
cout << "==>" << str << "<<==" << endl;

return 0;
}

测试结构如下:

1
2
3
4
5
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ g++ stringsplit.cpp -o stringsplit --std=c++17
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ ./stringsplit
==>c++11<<==
==>test<<==
==>split<<==

使用auto遍历map结构

很早以前C++中遍历map、set等复杂结构的时候需要写很长的代码来定义迭代器,自从出现了auto之后这种遍历简单了许多,最近发现针对map的遍历还有更简单的方法,使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <map>
#include <string>
#include <iostream>
using namespace std;

int main() {
map<string, int> m{{"tom", 20}, {"albert", 18}, {"bella", 19}, {"bily", 30}};

for (auto& [name, age] : m) {
if (age > 18)
cout << name << endl;
}

return 0;
}

测试结果如下:

1
2
3
4
5
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ g++ autonew.cpp -o autonew --std=c++17
albert@home-pc:/mnt/d/data/cpp/cplusplusadvance$ ./stringsplit
bella
bily
tom

总结

  • find_first_not_offind_last_not_offind_first_of 这系列函数功能虽简单,但是使用它们可以简化代码逻辑
  • 正则表达式是处理字符串查找的强有力的工具,合理的使用正则表达式可以达到事半功倍的效果,C++中请使用 std::regex
  • C++17中引入了结构化绑定声明,可以使用auto来声明多个变量,所有变量都必须用中括号括起来

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

做自己认为对的事情,剩下的交给时间~

2021-1-31 23:04:17

Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客