2013-02-23 18 views
5

我想以最短的代碼方式計算字符串中的所有數字。我試過這樣:使用帶字符串的標準算法的C++,使用isdigit的count_if,函數強制轉換

#include <string> 
#include <algorithm> 

unsigned countNumbers(const std::string s) { 
    return count_if(s.begin(), s.end(), isdigit); 
} 

錯誤消息:

a.cc: In function ‘unsigned int countNumbers(std::string)’: 
a.cc:5:45: error: no matching function for call to ‘count_if(std::basic_string<char>::const_iterator, std::basic_string<char>::const_iterator, <unresolved overloaded function type>)’ 
a.cc:5:45: note: candidate is: 
/usr/include/c++/4.6/bits/stl_algo.h:4607:5: note: template<class _IIter, class _Predicate> typename std::iterator_traits<_InputIterator>::difference_type std::count_if(_IIter, _IIter, _Predicate) 

我知道,count_if()函數希望像: 布爾(* F)(焦);作爲第三個參數,所以我試圖投功能:

unsigned countNumbers(const std::string s) { 
    return count_if(s.begin(), s.end(), reinterpret_cast<bool (*)(char)>(isdigit)); 
} 

錯誤消息:

a.cc: In function ‘unsigned int countNumbers(std::string)’: 
a.cc:5:80: error: overloaded function with no contextual type information 

我想也有點更長的版本,可以得到相同的編譯錯誤:

unsigned countNumbers(const std::string s) { 
    typedef bool (* f_ptr)(char); 
    f_ptr ptr = reinterpret_cast<f_ptr>(isdigit); 
    return count_if(s.begin(), s.end(), ptr); 
} 

我想避免的解決方案是創建一個適配器功能:

#include <string> 
#include <algorithm> 

bool is_digit(char c) { 
    return isdigit(c); 
} 

unsigned countNumbers(const std::string s) { 
    return count_if(s.begin(), s.end(), is_digit); 
} 

我的問題是如何在STD使用函數INT(* F)(INT)::這要布爾(* F)(INT)算法的功能,而無需創建適配器的功能,並且不使用lambda表達式?

我有,當我知道如何解決這個問題這將可以解決更多的問題,比如:

  • 檢查字符串是打印:find_if_not(s.begin(),s.end() ,isprint判斷)
  • 檢查字符串包含 「...。!?」:find_if(s.begin(),s.end(),ispunct判斷) 更多...

我只是想知道如何在標準C++中擁有更多的字符串可能性,這要感謝std :: algorithms 我是在網上很長一段時間搜索,我發現similar problem,但我沒有發現任何解決方案

+0

無法重現錯誤,工作正常使用g ++ 4.7.2 (Win7x64,MinGW)。 **編輯**:如果我使用'std :: isdigit'而不是'isdigit',則失敗。 – Zeta 2013-02-23 11:16:32

+0

如果你正在討論來自''頭部的函數,它們都[接受'int'並返回'int'](http://en.cppreference.com/w/cpp/string/byte/isdigit) 。 – jrok 2013-02-23 11:19:01

+0

將返回'int'作爲謂詞傳遞給算法的函數不是問題。算法是根據它們應用的操作來指定的,而不是它們謂詞的簽名。也就是說,if(f(x))...'不會**要求'f'返回'bool',只不過它的返回類型可以上下文轉換爲'bool'。 int的返回類型在這裏工作正常。錯誤消息是說它不能在重載版本的'isdigit'之間進行選擇,而不是'isdigit'具有錯誤的返回類型。 – 2013-02-23 12:56:58

回答

3

您可以使用靜態轉換來解析該函數​​。或者,如果這是你想要做的事很多,你可以使用模板來解決這個問題:

#include <string> 
#include <cctype> 
#include <algorithm> 

unsigned count(const std::string& s) { 
    return std::count_if(s.begin(), s.end(), static_cast<int(*)(int)>(std::isdigit)); 
} 

template <int(*Pred)(int)> 
unsigned foo(const std::string& s) { 
    return std::count_if(s.begin(), s.end(), Pred); 
} 

int main() { 
    count(""); 
    foo<std::isdigit>(""); 
    foo<std::isprint>(""); 
} 

static_cast是解決模棱兩可的「通常」的方式 - 它總是你所期望的,可以成爲其中的一部分更大的表達。

3

通過使用函數指針解析類型:

unsigned countNumbers(const std::string s) { 
    int (*isdigit)(int) = std::isdigit; 
    return count_if(s.begin(), s.end(), isdigit); 
} 

不要忘了包括<cctype>。 (demo

1

我發現下面同樣適用:

#include <ctype.h> 
    count_if(s.begin(), s.end(), ::isdigit); //explicitly select the C version of isdigit 

,但我必須搞清楚它只能如果C版本是這樣定義的函數 而非宏觀

,好了, std :: isdigit的static_cast可能是平臺之間最好的便攜式解決方案。

0

我給其他2種方案解決歧義與<locale> std::isdigit

  1. 使用lambda表達式:

    std::count_if(s.begin(), s.end(), [](char c){ return std::isdigit(c); })

或用明確的轉換:

std::count_if(s.begin(), s.end(), [](char c){ return std::isdigit(static_cast<int>(c)) != 0; }) 
  • 使用顯式模板類型(你還需要編寫迭代器類型):
  • std::count_if<std::string::const_iterator, int(*)(int)>(s.begin(), s.end(), std::isdigit)

    相關問題