今天做到一道题,给定一个类似于广义表的字符串(aaaa(bbbb(cccc,dddd),eeee(ffff)))
,表明的是各个人的层次关系。比如aaaa是bbbb和eeee的领导,bbbb是cccc和dddd的领导,现输入一个名称,比如ffff,要求输出其领导关系输出:aaaa>eeee>ffff
。
对于这样一个字母与括号混合在一起的字符串,我首先想到要对其进行拆分。不过字符串拆分的场景有很多,如果仅仅针对这一个问题,未免有些浪费,不如写一个较为通用的方法。于是想到尝试利用正则表达式进行拆分。
要匹配由字母组成的姓名很简单,由一个或多个大小写字母组成,即regex reg("[a-zA-Z]+");
。
常用到的函数有两个:
函数 | 功能 |
---|---|
bool regex_match(s,reg) | 字符串 s与表达式reg是否完全匹配(注意是完全匹配) |
bool regex_search(s,M,reg) | 字符串s中是否有子串与表达式reg匹配,结果对象存储在M中 |
接下来详细解释下这个 “ M ”。
引用了https://zh.cppreference.com/w/cpp/regex/regex_search
其类型为smatch,即smatch M;
若不存在该子串(匹配失败):
方法 | 返回值 |
---|---|
M.ready() | true |
M.empty() | true |
M.size() | 0 |
若存在该子串:
方法 | 返回值 |
---|---|
M.ready() | true |
M.empty() | false |
M.size() | 有标记子表达式的数量加 1 ,即 1+e.mark_count() |
M.prefix() | 前缀字符串 |
M.prefix().first | 指向 该匹配成功的子串 的前缀 的第一个字符的 迭代器 |
M.prefix().second | 指向 该匹配成功的子串 的前缀 的最后一个字符的下一个字符 的迭代器 |
M.suffix() | 后缀字符串 |
M.suffix().first | 同上,这个是后缀 |
M.suffix().second | 同上,这个是后缀 |
M[0].first | 指向匹配序列的首字符 的迭代器 |
M[0].second | 指向匹配数列的结尾后下一个字符 的迭代器 |
M[0].matched | true |
M[n].first | 匹配有标记子表达式 n 的序列的起始,或若子表达式不参与匹配则为 last |
M[n].second | 匹配有标记子表达式 n 的序列的结尾,或若子表达式不参与匹配则为 last |
M[n].matched | 若子表达式 n 参与匹配则为 true ,否则为 false |
终于介绍完了,下面是代码:
我想到的是用递归的方法实现划分(divide)函数:
- 调用regex_search方法,若匹配成功:
1. 将前缀中所有非,
的字符放入vector
2. 将匹配的字符放入vector
3. 对后缀调用divide方法 - 若匹配失败(当前串中已无要匹配的子串):
1. 将当前串所有字符放入vector
#include <iostream>
#include <string>
#include <vector>
#include <regex>
using namespace std;
void divide(string s,vector<string> &v,regex reg)
{
smatch mResult;
if (regex_search(s, mResult, reg)) {
for (auto it = mResult.prefix().first; it != mResult.prefix().second; it++) {
if (*it == ',')
continue;
v.push_back(string(1, *it));
}
v.push_back(string(mResult[0].first, mResult[0].second));
divide(mResult.suffix(), v, reg);
}
else {
for (auto it = s.begin(); it != s.end(); it++)
v.push_back(string(1, *it));
}
}
int main()
{
string source;
vector<string> mid;
cin >> source;
regex reg("[a-zA-Z]+");
divide(source, mid, reg);
vector<string>::iterator it;
for (it = mid.begin(); it != mid.end(); it++) {
cout << *it << ' ';
}
}
至于具体通用性如何,以后再修改吧哈哈