2017-01-25 31 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