2012-03-21 57 views
2

當submatch的索引指定爲-1時,sregex_token_iterator幾乎可以完美地作爲標記器工作。regex as tokenizer - 以分隔符開頭的字符串

#include <string> 
#include <regex> 
#include <iostream> 
using namespace std; 

int main() 
{ 
    string s("--aa---b-c--d--"); 
    regex r("-+"); 

    for (sregex_token_iterator it = sregex_token_iterator(s.begin(), s.end(), r, -1); it != sregex_token_iterator(); ++it) 
    { 
     cout << (string) *it << endl; 
    } 

    return 0; 
} 

打印出:

 
aa
b
c
d

不過遺憾的是它並不能很好地與帶分隔符e.g開頭的字符串工作

(注意前導空行)。

所以請注意,它實際上處理尾隨的定界符(因爲它不打印額外的空行)。

讀好像有標準是一個條款用於特異性處理後定界符很好地工作,即:

[re.tokiter] no 4.

如果到達序列的末尾(位置等於的端部序列迭代器)時,迭代器變得等於序列結束迭代器值,除非被枚舉的子表達式具有索引-1,在這種情況下,迭代器枚舉最後一個子表達式,該子表達式包含從結尾的所有字符最後的正則表達式與枚舉的輸入序列的末尾匹配,只要這個 不會是一個空的子表達式。

有誰知道這個看似不對稱行爲被指定的原因是什麼?

最後,有沒有一個優雅的解決方案,使這項工作? (這樣我們根本沒有空的條目)。

+0

我有點好奇,爲什麼你想標記生成器扔掉分隔符 - 這可能是在你的語言錯誤用分隔符開始輸入,如果標記器將其拋棄,則無法確定您的代碼將無法解析輸入。你能在語法層面上處理這個問題嗎? – sarnold 2012-03-21 01:11:01

+0

不,我現在沒有真正處理特定的問題,只是想知道這是否可行。 – ryaner 2012-03-21 01:18:56

+2

更優雅的解決方案:使用真正的標記器,如[Boost.Tokenizer](http://www.boost.org/doc/libs/1_49_0/libs/tokenizer/index.html)。 :P – Xeo 2012-03-21 01:23:30

回答

1

顯然你的正則表達式空字符串匹配之間 - 分隔符,一個簡單的(不一定是完美的解決方案)將放棄所有的字符串,長度爲零:

... 
string aux = (string) *it; 
if(aux.size() > 0){ 
    cout << aux << endl; 
} 
... 
+2

我會使用'aux.empty()'而不是檢查大小。 – 2012-03-21 06:55:16

+0

@JoachimPileborg你是對的aux.empty()是一個更清潔和更優雅的解決方案。 – mmisu 2012-03-21 22:12:57

1

它,當你通過-1作爲第三個參數你」似乎重新有效地進行拆分,這是拆分的預期行爲。第一個標記是第一個分隔符之前的任何內容,最後一個標記是最後一個分隔符之後的任何內容。在這種情況下,兩者恰好都是空字符串,並且傳統上split()最後會刪除所有空的標記,但保留這些標記的開頭。

出於好奇,你爲什麼不匹配令牌本身?如果"-+"是定界符正確的正則表達式,這應該與令牌:

regex r("[^-}+"); 
+0

有意思的答案。我從未注意到有關分裂的事實。你能指出我的其他字符串實現行爲相同嗎?再次,我只是想了解這種行爲,如果我確實解決了一個問題,我會選擇另一種解決方案=) – ryaner 2012-03-21 04:05:44