提问人:hdcdigi 提问时间:4/7/2023 更新时间:4/7/2023 访问量:55
通过正则表达式解析 C++ 多数据文本 [已关闭]
C++ multi data text parse via regex [closed]
问:
要解析的文本:
001 B001C001_230130_RQ7V V C 04:23:30:18 04:24:14:01 01:00:00:00 01:00:43:08
*ASC_SOP (1.000000 1.000000 1.000000)(0.000000 0.000000 0.000000)(1.000000 1.000000 1.000000)
*ASC_SAT 1.000000
我正在尝试将 *ASC_SOP 个三元组解析为 3x float[3] 数组。
源文件被加载并逐行传递给函数。当前函数如下所示:parse()
inline void parse(std::string &line) {
//regex to match edl id's camera reel and slope values
std::regex edlID("^([0-9]{3})");
std::regex camReel("([A-Za-z]([0-9]{3}))\\S+");
std::regex SOP("(?:[0-9][.][0-9]{6})");
std::smatch mID, reelID, sopMatch; //regex matchers
//check if there is an edlID. As per CM3600 spec this is always the first column
if(std::regex_search(line, mID, edlID)) {
std::regex_search(line, reelID, camReel); //next we check for a clip/reel name combo
std::cout << "EDL ID: " << mID[0] << " Clip: " << reelID[0] << std::endl;
}
}
将 *ASC_SOP 值和 ASC_SAT 值解析为相应浮点数的最佳方法是什么?正则表达式是最好的解决方案吗?还是基于令牌的字符串流更好?我的一个想法是去掉所有括号的行,然后用分隔符再次迭代。有没有人有一种有效的方法来处理这个问题?' '
答:
0赞
Jerry Coffin
4/7/2023
#1
假设您在这里关心的行始终遵循相同的基本模式:后跟三组 parens,每组包含三个浮点数,我可能会使用 .对于这样的情况,我通常从一个小的固定模式匹配器1 开始:*ASC_SOP
stringstream
std::istream &operator>>(std::istream &is, char const *pat) {
while (is.peek() == *pat) {
++pat;
is.ignore(1);
}
if (*pat)
is.setstate(std::ios::failbit);
return is;
}
有了这个,我们可以做这样的事情:
float a[3], b[3], c[3];
if (input >> "*ASC_SOP (" >> a[0] >> a[1] >> a[2] >> ")("
>> b[0] >> b[1] >> b[2] >> ")("
>> c[0] >> c[1] >> c[2] >> ")")
{
std::cout << "parsed ASC_SOP\n";
} else {
std::cerr << "Attempt at parsing ASC_SOP failed\n";
}
尽管模式匹配器本身并不完全直观,但至少在我看来,它似乎使代码的其余部分变得非常清晰易懂(一旦你理解了它的意图,模式匹配器也不是特别困难)。
- 根据具体情况,可以更详细地进行一些操作,例如,如果设置了流标志,则让它将模式中的任何空格与输入流中的任意数量的空格进行匹配,就像在 form 字符串中发生的那样 for 和 company。如果(例如)在结束部分和下一个开始部分之间可能有也可能没有空格(或可能制表符),这可能很有用。但是,一旦你有了基本的想法,如果需要,添加这样的东西就很容易了。
skipws
scanf
评论
0赞
hdcdigi
4/9/2023
这很好,谢谢。这背后的概念是否植根于操作员超载?这不是我熟悉的东西,所以需要研究它才能完全理解。我试图修改您的用法示例语句以说明该值,但它似乎不起作用。我尝试了以下方法,但它似乎没有返回值。我尝试使用标志并删除if语句中的空格。if
*ASC_SAT
if(sourceline_stringstream >> "*ASC_SAT " >> targetFloat){...}
skipws
0赞
Jerry Coffin
4/10/2023
是的,这是一个重载的运算符。
0赞
hdcdigi
4/10/2023
为什么我无法使用相同的方法获得 SAT 值?
0赞
Jerry Coffin
4/10/2023
@hdcdigi:不,至少在没有看到代码的情况下不会。两者之间没有太多明显的区别。
评论