C++中使用正则匹配问题
作者:DeRoy
C/C++可以用正则表达式吗?
答案肯定是可以的,那么,今天一个简单的输入scanf带你走进正则的世界
#include<stdio.h> int main() { printf("input digate:"); char str[100]; scanf("%[0-9]", str); //输入123456abc printf("%s", str); //打印123456 }
在scanf时输入任何一串以数字开始的字符,那么str里面只会保存字符里面的第一串数字
input digate:123456abc 123456
先给出一些简单的正则
限定符 | 含义 |
---|---|
%[0-9] | 数字集合 |
%[^0-9] | 非数字集合 |
%[a-zA-Z] | 字母集合 |
%[^a-zA-Z] | 非字母集合 |
预热好了,正题开始…
若要判断一个输入的QQ号是否有效,如何判断?
判断步骤:
- 长度大于5,小于等于11;
- 首位不能为0;
- 是否为纯数字?
C++string处理:
#include<iostream> using namespace std; int main() { string qq = "7466a2063"; if (qq.length() >= 5 && qq.length() <= 11) { // 2. 判断是否非'0'开头 if (qq[0] != '0') { // 3. 判断是否为纯数字 for each (char var in qq) { cout << var; if (var < '0' || var > '9') { cout << "不存在" << endl; return 0; } } cout << "存在" << endl; } else { cout << "不存在" << endl; } } else { cout << "不存在" << endl; } return 0; }
虽然功能实现了但是非常麻烦
正则处理:
#include<iostream> #include<regex> using namespace std; int main() { regex qq_reg("[1-9]\\d{4,11}"); string qq = "746632063"; smatch result; bool ret = regex_match(qq, result, qq_reg); cout << (ret ? "存在" : "不存在") << endl; return 0; }
笑出了声,一行正则匹配就解决了
是不是很方便呢?那么接下来便来看看如何使用「正则表达式」。
正则程序库(regex)
「正则表达式」就是一套表示规则的式子,专门用来处理各种复杂的操作。
std::regex是C++用来表示「正则表达式」(regular expression)的库,于C++11加入,它是class std::basic_regex<>针对char类型的一个特化,还有一个针对wchar_t类型的特化为std::wregex。
正则文法(regex syntaxes)
std::regex默认使用是ECMAScript文法,这种文法比较好用,且威力强大,
常用符号的意义如下:
符号 | 意义 |
---|---|
^ | 匹配行的开头 |
$ | 匹配行的结尾 |
. | 匹配任意单个字符 |
[…] | 匹配[]中的任意一个字符 |
(…) | 设定分组 |
\ | 转义字符 |
\d | 匹配数字[0-9] |
\D | \d 取反 |
\w | 匹配字母[a-z],数字,下划线 |
\W | \w 取反 |
\s | 匹配空格 |
\S | \s 取反 |
+ | 前面的元素重复1次或多次 |
* | 前面的元素重复任意次 |
? | 前面的元素重复0次或1次 |
{n} | 前面的元素重复n次 |
{n,} | 前面的元素重复至少n次 |
{n,m} | 前面的元素重复至少n次,至多m次 |
| | 逻辑或 |
上面列出的这些都是非常常用的符号,靠这些便足以解决绝大多数问题了。
匹配(Match)
字符串处理常用的一个操作是「匹配」,即字符串和规则恰好对应,而用于匹配的函数为std::regex_match(),它是个函数模板
bool regex_match(string s,regex pattern) bool regex_match(string s,smatch result,regex pattern) bool regex_match(s.cbegin()+i,s.cend(),smatch result,regex pattern) //从字符串的某个位置开始匹配?
我们直接来看例子:
#include<iostream> #include<regex> using namespace std; int main() { /*匹配*/ regex pattern("^1[3578]\\d{9}$"); //1开头,后面[3578]中的一个,九个数字 string s = "17779637570"; smatch result; bool ismatch = regex_match(s, result, pattern); if (ismatch) { cout << "匹配成功:" << result[0] << endl; } else cout << "匹配失败" << endl; return 0; }
匹配成功:17779637570
匹配成功并返回匹配到的结果
搜索(Search)
「搜索」与「匹配」非常相像,其对应的函数为std::regex_search,也是个函数模板,用法和regex_match一样,不同之处在于「搜索」只要字符串中有目标出现就会返回,而非完全「匹配」。
bool regex_search(string s,regex pattern) bool regex_search(string s,smatch result,regex pattern) bool regex_search(s.cbegin()+i,s.cend(),smatch result,regex pattern) //从字符串的某个位置开始匹配?
搜索给定字符串中是否存在与模式匹配的子串,如果存在则返回true。
同样可以用smatch result记录结果,但不同的是result[0]记录的是整个字符串中从左往右第一个匹配模式的子串。
假如有多个子串符合模式,若想知道result[0]中存储的是第几个子串,可以用result.position()函数,返回数从0开始。
我们直接来看例子:
#include<iostream> #include<regex> using namespace std; int main() { regex pattern("\\d+"); /*匹配一个到无穷个数字*/ string s = "51x41+(5-13/2)x3a"; smatch result; string::const_iterator iter_begin = s.cbegin(); string::const_iterator iter_end = s.cend(); while (regex_search(iter_begin, iter_end, result, pattern)) { cout << "查找成功:" << result[0] << endl; cout << "查找结果子串的在源串中的迭代器位置" << *result[0].first << endl; cout << "查找结果子串的在源串后面的位置" << *result[0].second << endl; iter_begin = result[0].second; //更新迭代器位置 } return 0; }
查找成功:51
查找结果子串的在源串中的迭代器位置5
查找结果子串的在源串后面的位置x
查找成功:41
查找结果子串的在源串中的迭代器位置4
查找结果子串的在源串后面的位置+
查找成功:5
查找结果子串的在源串中的迭代器位置5
查找结果子串的在源串后面的位置-
查找成功:13
查找结果子串的在源串中的迭代器位置1
查找结果子串的在源串后面的位置/
查找成功:2
查找结果子串的在源串中的迭代器位置2
查找结果子串的在源串后面的位置)
查找成功:3
查找结果子串的在源串中的迭代器位置3
查找结果子串的在源串后面的位置a
替换(Replace)
最后一种操作称为「替换」,即将正则表达式内容替换为指定内容,regex库用模板函数std::regex_replace提供「替换」操作。
string regex_replace(string s,regex p,string replace_str) //有其他重载用法
现在,给定一个数据为"he…ll…o, worl…d!", 思考一下,如何去掉其中误敲的“.”?
#include<iostream> #include<regex> using namespace std; int main() { char data[] = "he...ll..o, worl..d!"; regex reg("\\."); //正则匹配点. cout << regex_replace(data, reg, ""); //将正则匹配到的点替换成无,即删除点 return 0; }
hello, world!
删除了没必要的点,是不是贼方便…
对字符串data中与模式匹配的所有子串进行相应的字符串替换,替换字符串引用匹配子串中的内容,引用方法如下
转义序列 | 替换为 |
---|---|
$n | 匹配第n个捕捉组的字符串。例如$l表示第一个捕捉组,$2表示第二个,依此类推 |
$& | 匹配整个正则表达式的字符串,等同于$0 |
$` | 在源字符串中,在匹配正则表达式的子字符串左侧的部分 |
$’ | 在源字符串中,在匹配正则表达式的子字符串右侧的部分 |
$$ | 美元符号 |
#include<iostream> #include<regex> using namespace std; int main() { char data[] = "001-Neo,002-Lucia"; regex reg("(\\d+)-(\\w+)"); cout << regex_replace(data, reg, "$1 name=$2"); return 0; }
001 name=Neo,002 name=Lucia
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。