减少 std::正则表达式编译时间 C++
Reducing std::regex compile time in C++
我正在使用std::regex r("-?[0-9]*(.[0-9]+)?(e-?[0-9]+)?")
来验证数字(整数/定点/浮点)。MWE如下:
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <algorithm>
using namespace std;
bool isNumber(string s) {
// can ignore all whitespace
s.erase(remove(s.begin(), s.end(), ' '), s.end());
std::regex r("-?[0-9]*(.[0-9]+)?(e-?[0-9]+)?");
return regex_match(s, r);
}
int main() {
std::vector<string> test{
"3", "-3", // ints
"1 3", " 13", " 1 3 ", // weird spacing
"0.1", "-100.123123", "1000.12312", // fixed point
"1e5", "1e-5", "1.5e-10", "1a.512e4", // floating point
"a", "1a", "baaa", "1a", // invalid
"1e--5", "1e-", //invalid
};
for (auto t : test) {
cout.width(20); cout << t << " " << isNumber(t) << endl;
}
return 0;
}
我注意到与我预期的相比,编译时间相当长:
-
gcc 5.4 -O0 -std=c++11
, 2.3 秒 -
gcc 5.4 -O2 -std=c++11
, 3.4 秒 -
clang++ 3.8 -O0 -std=c++11
, 1.8 秒 -
clang++ 3.8 -O2 -std=c++11
, 3.7 秒
我将其用于在线评委提交,该提交在编译阶段有时间限制。
所以,令人讨厌的问题:
- 为什么编译时间这么大?我的印象是,当我在 vim/emacs/grep/ack/ag 等(在同一台机器上)中使用正则表达式时,编译花费的时间确实比这少得多。
- 有没有办法减少正则表达式在C++中的编译时间?
您当然可以通过适当地转义小数点来减轻正则表达式的计算负载: -?[0-9]*(.[0-9]+)?(e-?[0-9]+)?
这当然可以防止您在以下数字上返回误报:"1 3"(不要担心这是一件好事,那是 2 个数字。但是在这种情况下和许多其他情况下,当您屈服于使用正则表达式时,"现在您有 2 个问题"。
使用 istringstream
将为此问题提供更专业、更可靠的解决方案:
bool isNumber(const string& s) {
long double t;
istringstream r(s);
return r >> t >> ws && r.eof();
}
现场示例
相关文章:
- C++为构建时间获取QDateTime的可靠方法
- 从持续时间构造std::chrono::system_clock::time_point
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 使用简单类型列表实现的指数编译时间.为什么
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在已经使用Git的情况下减少编译时间
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 从文本文件中读取时钟时间和事件时间并进行处理
- 具有未知值时的时间复杂性
- 如何减少花费的时间
- C++在变量给定的指定时间内关闭电脑
- rcpp函数中的清理时间很长
- C++:floor unix时间戳到UTC月份
- 如何在c++中录制具有精确帧时间戳的视频
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- KMP算法和LPS表构造的运行时间
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间