2013-04-12 166 views
0

我一直在更新我幾乎兩年前寫過的程序,並且遇到了一個調用來從字符串中刪除所有標點符號和空格。刪除標點符號查詢

該調用工作正常,但我不確定它是否是最有效的方法。

的代碼行低於:

tempMessage.erase(remove_if(tempMessage.begin(), tempMessage.end(), (int(*)(int))ispunct), tempMessage.end()); 

我沒有,我想出了這個或它是如何放在一起回味,但我希望能夠充分理解這一呼籲。

我得到的std :: string.erase擺脫了第一個參數,直到第二個參數。我還可以看到remove_if是如何定義開始點和結束點的,但任何人都可以告訴我remove_if調用的第三個參數來自哪裏?

我不記得爲什麼我的生活需要(int(*)(int))。

在查看代碼時,任何人都可以改進它,或使其更高效嗎?

謝謝

回答

1

首先,這一般不起作用;它似乎(並且它可能與一些編譯器一起工作)。您無法將char傳遞給 一個參數版本ispunct,而不會產生未定義的 行爲。

至於用於鑄造的原因:標準同時定義了 一個參數ispunct功能兩參數 ispunct函數模板。爲了正確 實例化模板函數erase,編譯器需要 來知道ispunct的確切類型。要知道 ispunct的確切類型,編譯器需要能夠在函數模板上進行類型推演 。爲了進行類型推導,編譯器需要知道預期的類型。在 中有一個循環依賴關係,其中明確的投射(或者看起來像 明確投射)解決。

,因爲使用的ispunct結果的一個參數版本 未定義的行爲,並使用兩個參數版本不會 編譯除非你提供額外的參數(使用 std::bind,例如),任何人做任何字符串處理 C++將已經寫在他的工具箱 來處理這個功能對象,而且會寫類似:

tempMessage.erase(
    std::remove_if(tempMessage.begin(), tempMessage.end(), IsPunct()), 
    tempMessage.end()); 

如何實現IsPunct要看你的需求與問候 進行本地化。最簡單的版本就是:

struct IsPunct 
{ 
    bool operator()(char ch) const 
    { 
     return ::ispunct(static_cast<unsigned char>(ch)); 
    } 
}; 

使用ctype方面的locale版本是有點 更復雜(你可能希望它的 locale的副本,以及參考保持到面,只是爲了確保 參考面不會消失)。

+0

看來我當時正在尋找一個快速解決方案,而且這樣做的確如此。你能解釋一下你在答案中定義的結構嗎?它看起來像是返回true,如果char是一個punct字符,但我不明白ispunct調用之前的兩個分號。我也不是很熟悉bool操作符()const的實現。你還可以擴展這個嗎?麻煩抱歉。 – Matthew

+0

沒問題。 '::'是一個範圍解析運算符。它只是確保我們從''得到'ispunct',而不是另一個。 (這裏不需要)'bool operator()(...)'是一個函數調用操作符:它意味着編譯器可以像調用函數一樣「調用」對象。這樣的對象被稱爲功能對象或函子,並且廣泛用於C++。 –

+0

只是爲了我自己的清晰。如何將一個'char'傳遞給'int ispunct(int ch)'未定義的行爲,但傳遞一個'unsigned char'是* not *?前者是否不在標準(4.5/4.7)中整體促銷的結果範圍內,如果不是,後者又如何? – WhozCraig