c++多数据文本解析通过正则表达式



待解析文本:

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值解析为相应的浮点数的最佳方法是什么?regex是最好的解决方案吗?还是基于令牌的stringstream更好?我的一个想法是去掉所有括号的行,然后用' '分隔符再次迭代。有人有有效的方法来处理这个问题吗?

假设您在这里关心的行始终遵循相同的基本模式:*ASC_SOP后面跟着三组父元素,每个父元素包含三个浮点数,我可能会使用stringstream。对于这种情况,我通常从一个小的固定模式匹配器1:

开始
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_SOPn";
} else {
std::cerr << "Attempt at parsing ASC_SOP failedn";
}

虽然模式匹配器本身并不完全直观,至少对我来说,它似乎使其余的代码非常清晰易懂(一旦您理解了它的目的,模式匹配器也不是特别困难)。


  1. 根据具体情况,可以更详细地说明这一点,例如,如果设置了流skipws标志,让它将模式中的任何空白与输入流中的任意数量的空白匹配,就像scanf和公司的formst字符串中发生的那样。这可能是有用的,如果(例如)可能有,也可能没有一个空格(或可能制表符)之间的结束页和下一个开始页。但是一旦你有了基本的想法,如果需要的话,添加这样的东西就很容易了。

最新更新