2017-01-25 16 views
4

std::regex r("-?[0-9]*(.[0-9]+)?(e-?[0-9]+)?")を使用して数値(整数/固定小数点/浮動小数点数)を検証しています。 MWEは以下の通りです:C++でstd :: regexのコンパイル時間を短縮する

#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秒

私はオンライン判事の提出にこれを使用します。これは、コンパイル段階に期限があります。

ので、obivous質問:

  • なぜコンパイル時間が非常に大きいのですか?私はvim/emacs/grep/ack/agなど(同じマシン上で)正規表現を使用するとコンパイルが実際にはこれよりもはるかに少ないという印象を受けています。
  • C++の正規表現のコンパイル時間を短縮する方法はありますか?
+0

それは正規表現のあまり、コンパイル時間はありませんが、実装するために必要なコードのすべてのすべての正規表現機能10の正規表現を使用する時間を比較してください。 – chris

+0

@chrisが正しいようです。 -save-tempsでコンパイルして、結果の中間ファイルのサイズを調べてください。 –

+0

正規表現はおそらくバックエンドに有限状態マシンを構築しようとしています。それには多くの時間がかかります。おそらくそれはあなたが見ているものです。 – NathanOliver

答えて

1

あなたは確かに適切に小数点をエスケープして、正規表現の計算負荷を軽減することができます:-?[0-9]*(\.[0-9]+)?(e-?[0-9]+)?これはもちろんのような番号に偽陽性を返すからあなたを防ぐ:(「1〜3」それはです心配しないでください良いものは2つの数字だった。)しかし、この場合と他の多くの場合正規表現を使用してストップするとき"Now you have 2 problems"

istringstreamを使用すると、この問題へのより特化した、堅牢なソリューションを提供します:

bool isNumber(const string& s) { 
    long double t; 
    istringstream r(s); 

    return r >> t >> ws && r.eof(); 
} 

Live Example

関連する問題