正则表达式
首先简单地介绍一下正则表达式,正则表达式即为一串规则序列,记为pattern,常用于在字符串中匹配符合pattern的子字符串。若要在C++中使用正则表达式,需要#include<regex>。
本文中需要用到的标识有:
标识 | 解释 |
---|---|
\d | 匹配一个0-9的数字 |
+ | 匹配一个或多个 |
简单示例如下:
pattern="\d+" #表示匹配一个或多个数字
str="aa12bb34" #使用pattern匹配str时,匹配的结果为12和34,这样就完成了从字符串中取出数据的任务
进入正题
有时候,算法题要求我们自己处理输入,有些算法题给出的输入并不能通过形如while(cin>>a>>b)这样的简单句式来处理。打个比方,算法题给出的输入是一个二维矩阵,其输入形式为
[[1,0,7],[2,0,6],[3,4,5],[0,3,0],[9,0,20]]
如果要通过字符串操作去处理这样的输入将会比较麻烦,因此,这时候使用正则表达式更加简单高效。同时,为了节省我们测试算法时手动输入的时间,以下示例也使用了文件流的方法令程序自动读取文件中的输入数据并输出。提交代码时只需要将示例中的fin, fout改成cin, cout并删除文件流操作代码段即可。
#include <iostream>
#include<fstream> //用于文件流操作
using namespace std;
#include<vector>
#include<regex> //正则表达式库
int main() {
ifstream fin;//定义一个输入流
fin.open("input.txt");//打开要读取的文件
ofstream fout;//定义一个输出流
fout.open("out.txt");//打开要输出的文件
//code begin
string input;//使用input存储一行字符串
while(getline(fin,input)){//使用getline获取输入文件中的一行字符串
vector<vector<int>>grid;//定义存储输入的矩阵
//定义一个pattern
//由于'\x'的形式为转义字符,所以需要再加一个'\'取消转义
//'\\['即表示字符'[',而'\\d'表示标识符'\d'
//该pattern的作用为匹配由中括号包括的矩阵的一行字符
//以上文示例的矩阵为例,[1,0,7]就是一个满足pattern的子字符串
regex pattern("\\[(\\d+,)+\\d+\\]");
//定义res用于储存匹配结果
smatch res;
//获取字符串的头和尾
string::const_iterator start=input.begin();
string::const_iterator end=input.end();
//regex_search第一和第二个参数表示匹配的开始位置和结束位置,
//第三个参数为一个匹配结果,第四个参数为正则表达式
while(regex_search(start,end,res,pattern)){
//使用tmp存储一个匹配结果
string tmp=res[0];
//再次匹配,这次需要矩阵一行的具体数据
//例如字符串“[1, 0, 7]”,其匹配结果即为子字符串“1”,“0”和“7”
//(注意上述的数据皆为string类型)
regex pattern2("\\d+");
smatch res2;
string::const_iterator start2=tmp.begin();
string::const_iterator end2=tmp.end();
//定义一个一维数组用于储存矩阵的一行
vector<int>new_row;
while(regex_search(start2,end2,res2,pattern2)){
string tmp_2=res2[0];
//使用atoi函数将string类型转为int类型,并存入数组
new_row.push_back(atoi(tmp_2.c_str()));
//重设匹配开始位置为上一个匹配结果之后
start2=res2[0].second;
}
//将矩阵的一行数据存入矩阵中
grid.push_back(new_row);
//重设匹配开始位置为上一个匹配结果之后
start=res[0].second;
}
//至此,我们就获得了一个输入矩阵,用于之后的算法代码。
}
//code end
//关闭文件
fin.close();
fout.close();
return 0;
}