练习17.14 编写几个正则表达式,分别触发不同错误。运行你的程序,观察编译器对每个错误的输出。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
try {
regex r("[[:alnum:]+\\.(cpp|cxx|cc)$", regex::icase);
}
catch(regex_error e){
cout << e.what() << "\ncode: " << e.code() << endl;
}
try
{
regex t("[[:alnum]]+\\.(cpp|cxx|cc)$");
}
catch (regex_error e)
{
cout << e.what() << "\ncode: " << e.code() << endl;
}
}
练习17.15 编写程序,使用模式查找违反“i在e之前,除非在c之后”规则的单词。你的程序应该提示用户输入一个单词,然后指出此单词是否符合要求。用一些违反和未违反的单词测试你程序。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string s;
string parttern("[^c]ei");
parttern = "[[:alpha:]]*" + parttern + "[[:alpha:]]*";
regex r(parttern);
smatch result;
while (cin >> s) {
if (regex_search(s, result, r)) {
cout << "wanted: " << result.str() << endl;
}
else {
cout << "not wanted: " << s << endl;
}
}
}
练习17.16 如果前一题程序中的regex对象用“[^c]ei”进行初始化,将会发生什么?用此模式测试你的程序,检查你的答案是否正确。
输出想要的字符串为 ?ei。其中?代表非c的字符。
练习17.17 更新你的程序,令它查找输入序列中所有违反"ei"语法规则的单词。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string parttern("[^c]ei");
regex r("[[:alpha:]]*"+parttern+"[[:alpha:]]*", regex::icase);
string svec = "freind receipt receive theif";
for (sregex_iterator it(svec.begin(), svec.end(), r), end_it; it != end_it; ++it) {
cout << it->str() << endl;
}
}
练习17.18 修改你的程序,忽略包含"ei"但非拼写错误的单词,如"albeit"和"neighbor"。
【转载,侵删】
#include <iostream>
#include <string>
#include <regex>
#include <fstream>
#include <vector>
int main(int argc, char **argv)
{
using namespace std;
ifstream file(argv[1]);
if (!file)
{
cerr << "open file error!";
exit(1);
}
string p("[^c]ei");
p = "[[:alpha:]]*" + p + "[[:alpha:]]*";
regex reg(p, regex::icase);
string temp, str;
while (getline(file, temp))
str = str + temp + "\n";
vector<string> vec{ "albeit","beige","feint","heir","reign","their",
"counterfeit","foreign","inveigh","rein","veil","deign",
"forfeit","inveigle","seize","veineiderdown","freight",
"leisure","skein","weigheight","heifer","neigh","sleigh",
"weighteither","height","neighbour","sleight","weirfeign",
"heinous neither surfeit weird" };
for (sregex_iterator it(str.begin(), str.end(), reg), end_it; it != end_it; ++it)
{
if (find(vec.begin(), vec.end(), it->str()) != vec.end())
continue;
cout << it->str();
system("pause");
auto pos = it->prefix().length();
cout << it->prefix().str().substr(pos > 40 ? pos - 40 : 0) << "[> " << it->str() << "<]" << it->suffix().str().substr(0, 40) << endl;
}
system("pause");
return 0;
}
练习17.19 为什么可以不先检查m[4]是否匹配了就直接调用m[4].str()?
调用m[4].str()的情况下都有比较苛刻的比较条件。
而且在else中,m[4].str()有三种可能匹配情况。
练习17.20 编写你自己版本的验证电话号码程序。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
bool valid(const smatch& m)
{
if (m[1].matched) {
return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
}
else{
return !m[3].matched && m[4].str() == m[6].str();
}
}
int main()
{
string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
regex r(phone);
smatch m;
string s;
while (getline(cin, s)) {
for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it) {
if (valid(*it)) {
cout << "valid: " << it->str() << endl;
}else{
cout << "not valid" << it->str() << endl;
}
}
}
}
练习17.21 使用本节中定义的valid函数重写8.3.2节(第289页)中的电话号码程序。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <regex>
struct PersonInfo {
std::string name;
std::vector<std::string> phones;
};
bool valid(const std::smatch &m);
bool read_record(std::istream &is, std::vector<PersonInfo> &people);
void format_record(std::ostream &os, const std::vector<PersonInfo> &people);
int main()
{
using namespace std;
vector<PersonInfo> people;
string filename;
cout << "enter input file name:";
cin >> filename;
ifstream fin(filename);
if (read_record(fin, people))
{
cout << "enter output file name:";
string outname;
cin >> outname;
ofstream fout(outname, ofstream::trunc); //覆盖文件:trunc
format_record(fout, people);
}
else
cout << "open file error:" << filename << endl;
system("pause");
return 0;
}
bool valid(const std::smatch &m)
{
if (m[1].matched)
return m[3].matched && (m[4].matched == 0 || m[4] == " ");
else
return !m[3].matched&&m[4].str() == m[6].str();
}
bool read_record(std::istream &is, std::vector<PersonInfo> &people)
{
if (is)
{
std::string line, word;
while (getline(is, line)) //读取一行到line
{
PersonInfo info;
std::istringstream record(line); //关联流到line,把record绑定到要读取的行line
record >> info.name; //把流中第一个字符串输入到name,这一行的第一个,也就是名字
while (record >> word)
info.phones.push_back(word);//把名字后面的电话号码保存
people.push_back(info); //添加一个联系人
}
return true;
}
else
return false;
}
void format_record(std::ostream &os, const std::vector<PersonInfo> &people)
{
std::string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
std::regex reg;
try {
reg.assign(phone);
}
catch (std::regex_error e)
{
std::cout << e.what() << "\ncode: " << e.code() << std::endl;
}
std::smatch m;
for (const auto &x : people)
{
std::ostringstream formatted, badNums;
for (const auto &n : x.phones)
{
for (std::sregex_iterator it(n.begin(), n.end(), reg), end_it; it != end_it; ++it)
{
if (!valid(*it))
badNums << " " << n; //将数据放入流,暂时保存
else
formatted << " " << n;
}
}
if (badNums.str().empty())
os << x.name << " " << formatted.str() << std::endl; //将流中的数据以string的形式放入os流中
else
std::cerr << "file error: " << x.name << " invalid number " << badNums.str() << std::endl;
}
}
练习17.22 重写你的电话号码程序,使之允许在号码的第三部分之间放置任意多个空白符。
"(\\()?(\\d{3})(\\))?([[:blank:]]*)?(\\d{3})([[:blank:]]*)?(\\d{4})"
练习17.23 编写查找邮政编码的正则表达式。一个美国邮政编码可以由五位或九位数字组成。前五位数字和后四位数字之间可以用一个短横线分隔。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main()
{
string code = "(\\d{5})([-])?(\\d{4})?";
regex r(code);
smatch m;
string s;
while (getline(cin, s)) {
for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it) {
if ((*it)[3].matched || (*it)[1].matched) {
cout << "valid: " << it->str() << endl;
}
else {
cout << "not valid: " << it->str() << endl;
}
}
}
}
练习17.24 编写你自己版本的重排电话号码格式的程序。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
using namespace std::regex_constants;
int main()
{
string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
regex r(phone);
smatch m;
string s;
string fmt = "$2.$5.$7";
while (getline(cin, s)) {
cout << regex_replace(s, r, fmt) << endl;
}
return 0;
}
练习17.25 重写你的电话号码程序,使之只输出每个人的第一个电话号码。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
using namespace std::regex_constants;
int main()
{
string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
regex r(phone);
string s;
string fmt = "$2.$5.$7";
while (getline(cin, s)) {
smatch m;
regex_search(s, m, r);
if (!m.empty()) {
cout << m.prefix() << m.format(fmt) << endl;
}
}
}
练习17.26 重写你的电话号码程序,使之多于一个电话号码的人只输出第二个和后续的电话号码。
cout << m.prefix() << m.suffix()<< endl;
练习17.27 编写程序,将九位数字邮政编码的格式转换为ddddd-dddd。
#include <iostream>
#include <string>
#include <regex>
using namespace std;
using namespace std::regex_constants;
int main()
{
string code = "(\\d{5})(\\d{4})?";
regex r(code);
smatch m;
string fmt = "$1-$2";
string s;
while (getline(cin, s)) {
cout << regex_replace(s, r, fmt,format_no_copy) << endl;
}
return 0;
}