c++ - 将 istream_iterator 与 regex_token_iterator 结合使用
问题描述
是否可以将 anistream_iterator
与regex_token_iterator
类似的类似:
std::copy(
std::sregex_token_iterator(std::istreambuf_iterator<char>{ifs},
std::istreambuf_iterator<char>{}, r, 1), std::sregex_token_iterator{},
std::ostream_iterator<std::string>(std::cout)
);
给这个一点背景。我是编程新手,我试图解决一个问题,我想删除 ifstream 中的所有内容,除了数字。我这样做是为了练习和学习。
输入文件如下所示:
aoisdnf 2 aopsjmdf 4 anpoidsnian 5 ainsdf 12 paalknshndf 43 aoksjhndfal 4 aslkdfoo 9 hjalkgshgdfk 4
解决方案应如下所示:
2 4 5 12 43 4 9 4
我的第一种方法是:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctype.h>
int main()
{
std::ifstream ifs ("C:/Users/../whitespace_seperated_integers.txt", std::ifstream::in);
std::string tmp;
std::vector<int> vector;
for (auto it = std::istreambuf_iterator<char>{ifs}; it != std::istreambuf_iterator<char>{}; ++it) {
if (*it >= '0' && *it <= '9') tmp.append(1, *it);
else if (!tmp.empty()){
vector.push_back(std::stoi(tmp));
tmp.clear();
}
}
if (!tmp.empty()) vector.push_back(std::stoi(tmp));
for(const auto i : vector){
std::cout << i << " ";
}
效果很好,但后来我有了用正则表达式解决这个问题的想法,这导致了这个解决方案:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctype.h>
#include <regex>
int main()
{
std::ifstream ifs ("C:/Users/../whitespace_seperated_integers.txt", std::ifstream::in);
std::string puf;
std::vector<std::string> vector;
std::string line;
char wts = ' ';
while(getline(ifs ,line, wts)){
puf += line;
}
std::regex r(R"([^\d]*(\d+))");
std::copy(std::sregex_token_iterator(puf.begin(), puf.end(), r, 1), std::sregex_token_iterator(), std::back_inserter(vector));
std::vector<int> vec;
std::smatch sm;
while(std::regex_search(puf, sm, r))
{
vec.push_back(std::stoi(sm[1]));
/* std::cout << sm[1] << '\n';*/
puf = sm.suffix();
}
for(const auto i : vec){
std::cout << i << " ";
}
}
但我对这段代码并不满意,所以我试图弄清楚如何改进它。我试图将 istream_iterator 与 regex_token_iterator 结合起来,但我无法弄清楚它是如何工作的。
解决方案
如果您真的想使用std::sregex_token_iterator
,那么您可能需要选择不同的方法。
对于给定的字符串,您要提取数字。我们可以改变流动角度并使用不同的算法。如果我们确实看到所有不是数字的东西作为分隔符,我们可以使用std::sregex_token_iterator
带有索引参数 -1 的 来分割字符串。
所以,秘密是新的分隔符。然后结果是单行
#include <iostream>
#include <regex>
#include <vector>
#include <iterator>
#include <string>
int main()
{
// The test string
std::string test{"aoisdnf 2 aopsjmdf 4 anpoidsnian 5 ainsdf 12 paalknshndf 43 aoksjhndfal 4 aslkdfoo 9 hjalkgshgdfk 4"};
// regex for anything but a digit
const std::regex re {R"([\D]+)"};
// Get all digits from the test string
std::vector<std::string> token(std::sregex_token_iterator(test.begin(),test.end(),re, -1), {});
// Output result
std::copy(token.begin(), token.end(), std::ostream_iterator<std::string>(std::cout," "));
return 0;
}
推荐阅读
- c - 为什么逻辑语句 !0x00 在 C 中返回 0x01?
- node.js - Socket.io 使用 Reactjs 和 Expressjs 在 GET 请求中发送数据
- usb - DFU模式下的STM32F04仅在电池供电时识别(Win10)
- .htaccess - Symfony 4 + AWS Cloudfront 作为 PageCache + AWS ELB 导致首页上无休止的重定向
- c++ - 当问题的性质完全不同时,为什么要使用 C2259?
- python - 如何查看任务是否完成?
- java - 如何制作录音机
- java - 为什么将RelativeLayout的“layout_width”设置为布局xml中的固定值不起作用?
- html - 在移动设备上的电子邮件预览中隐藏 HTML 横幅
- c# - c# 中是否有 f'{}' 的等价物