使用c++正则表达式验证ASCII GnuPlot文件

Validate ASCII GnuPlot file with c++ regex

本文关键字:GnuPlot 文件 ASCII 验证 c++ 正则表达式 使用      更新时间:2023-10-16

我一直在努力做到这一点,但似乎无法使事情按我希望的方式进行。

我有一个ASCII文件,其中包含数百万行浮点值,用空格分隔。使用std::istream_iterator<double>读取这些值很简单,但我想预先验证文件,以确保它确实按照我描述的方式进行了格式化。由于只有一种正确的格式,以及如何对其进行错误格式化的方法,我想使用std::regex进行处理。

这就是我想到的:

std::string begln( "^" );
std::string endln( "$" );
std::string fp( "[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?." );
std::string space( "[[:space:]]{1}" );
std::regex regexp( "(" + begln + fp + space + fp + space + fp + endln + ")+" );

我想表达的是:一条线由线的开始和结束之间的东西组成,它由三组用一个空格分隔的浮点值组成,我正在寻找其中的一条或多条线。

我希望一个有效的数据文件只有一个匹配项,没有前缀和后缀。

但是,嘿,既然这些值将进入std::vector<std::array<double, 3>>,为什么我不重用regex机制并从匹配列表中获取值呢?如果文件是有效的,那么一个绝对平凡的regex可以只匹配单个行,并构造一个std::sregex_iterator来迭代这些行。在这一点上,无论是再次使用regex还是std::stringsteam,如何从一行的单个std::string中获得值只是一个问题。

为什么不呢?您之所以不希望这样做,是因为regex绝对是过度使用。它们可以匹配更复杂的语法,并且能够在运行时阅读这些语法。这种灵活性付出了高昂的代价。必须包括所有可能的解析器。当前没有一个编译器足够聪明,可以看到您只是将[[:space:]]用作正则表达式。(事实上,没有一个C++编译器或链接器知道regex——这纯粹是一个库的东西)。

相比之下,operator>>是重载的,编译器可以准确地看到您在编译时使用的重载。链接器被告知这一点,并且仅包括相关代码。

此外,CPU分支预测器将很快注意到operator>>几乎总是成功,这是进一步的加速。您的正则表达式代码不太可能以同样的方式受益——[0-9]*中的条件部分至少有一层间接更深。