CPP正则表达式

定义

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表达式中的通配符

例如:\d匹配任意数字,也就说\d可以匹配0,也可以匹配1,还有2,3,…9都可以匹配。

\d 匹配一个数字,也就是匹配0-9
\w匹配单词字符,也就是匹配a-z和A-Z还有’_’。
\s匹配空白字符(空格)。
\b匹配单词边界(匹配位置而不是实际的字符,边界可以是符号或空格)
. 匹配任意字符

正则表达式中的量词

匹配前面的字符0次或1次
* 匹配前面的字符0次或多次
+ 匹配前面的字符1次或者多次
{m} 匹配前面表达式m次
{m,} 匹配前面表达式至少m次
{,n} 匹配前面的正则表达式最多n次
{m,n} 匹配前面的正则表达式至少m次,最多n次

例子:
“abc+”可以匹配abc, abcc, abccc, abcccc, abccccc,以此类推。
“yts*”可以匹配 yt, yts, ytss, ytsss, ytsss
“y{1,5}”可以匹配 y, yy, yyy, yyyy, yyyyy.

转义字符

当想要匹配一些上面的通配符或者量词中的符号时,就需要用到转义字符
例如:既然’+’在正则表达式中是一个量词,那么如何让正则表达式匹配加号呢?
\+表示匹配一个加号,类似的\?匹配一个问号,\. 匹配一个句点

原始字符串

在C++11中原始字符串具有如下的形式:R”(data)”
具体来说,以大写字母R开头,后面是一个引号对和一个小括号对,在小括号中的内容才是字符串的正真内容,其中的内容不会反生转义。也就是说R”(\n)”就是字符串\n,而不是换行符。因此,如果在原始字符串中想要匹配一些诸如?这样的符号的时候,就必须使用/?
我们在写正则表达式的时候一定要用原始字符串!

regex_replace

在regex头文件还定义了一个regex_replace函数,用来进行正则表达式的替换。
regex_replace(string data, regex re, string new_string);
功能是将data中满足正则表达式re的所有位置替换成new_string,返回替换后的字符串。注意:regex_replace不会修改输入字符串,它会创建一个新的字符串进行替换后返回。

两道来自$c^4$的例题:

题意:从左到右扫描输入的句子:如果句子中有超过 3 个连续的 6,则将这串连续的 6 替换成 9;但如果有超过 9 个连续的 6,则将这串连续的 6 替换成 27。其他内容不受影响,原样输出。

1
2
3
4
5
6
7
8
9
10
11
12
#include<bits/stdc++.h>
using namespace std;
int main()
{
string str;
getline(cin,str);
str=regex_replace(str,regex(R"(6{10,})"),"27");//匹配10个9或以上
str=regex_replace(str,regex(R"(6{4,9})"),"9");
cout<<str<<endl;

return 0;
}

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:
无论用户说什么,首先把对方说的话在一行中原样打印出来;
消除原文中多余空格:
把相邻单词间的多个空格换成 1 个空格
把行首尾的空格全部删掉
把标点符号前面的空格删掉;
把原文中所有大写英文字母变成小写,除了 I;
把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词;
把原文中所有独立的 I 和 me 换成 you;
把原文中所有的问号?换成惊叹号 !;
在一行中输出替换后的句子作为 AI 的回答。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;string str;
cin>>n;getline(cin,str);
while(n--){
getline(cin,str);
cout<<str<<endl;
str=regex_replace(str,regex(R"(\s+)")," ");//处理多个空格
if(str.back()==' ')str.pop_back();
if(str.front()==' ')str.erase(str.begin());//处理行末行首空格
str=regex_replace(str,regex(R"( !)"), "!");
str=regex_replace(str,regex(R"( ,)"), ",");
str=regex_replace(str,regex(R"( \.)"), ".");
str=regex_replace(str,regex(R"( \?)"), "?");
str=regex_replace(str,regex(R"( ')"), "'");//处理符号前的空格
for(auto &a:str)
a=(a=='I'?'I':tolower(a));
str=regex_replace(str,regex(R"(\bcan you\b)"),"_I can");
str=regex_replace(str,regex(R"(\bcould you\b)"),"_I could");//处理can you,因为后面还要处理I所以都替换成_I
str=regex_replace(str,regex(R"(\bI\b)"),"you");
str=regex_replace(str,regex(R"(\bme\b)"),"you");
str=regex_replace(str,regex(R"(\?)"),"!");
str=regex_replace(str,regex(R"(_I)"),"I");//替换_I
cout<<"AI: "<<str<<endl;
}

return 0;
}