簡體   English   中英

C ++使用帶字符串的標准算法,帶有isdigit的count_if,函數轉換

[英]C++ using standard algorithms with strings, count_if with isdigit, function cast

我想以最短的代碼方式計算字符串中的所有數字。 我試過這樣的方式:

#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()想要的函數如下:bool(* f)(char); 作為第三個參數,所以我試圖強制轉換函數:

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 :: algorithm的函數中使用函數int(* f)(int),這些函數需要bool(* f)(int)而不創建適配器函數而不使用lambda表達式?

當我知道如何解決問題時,我會遇到更多問題,例如:

  • 檢查字符串是否可打印:find_if_not(s.begin(),s.end(),isprint)
  • 檢查字符串是否包含“,。!?...”:find_if(s.begin(),s.end(),ispunct)等等...

我只是想知道如何在標准C ++中有更多的字符串可能性,這要歸功於我長時間在互聯網上搜索的std :: algorithms,我發現了類似的問題 ,但我找不到解決方法

您可以使用靜態強制轉換來解析該函數​​。 或者,如果您想要做很多事情,可以使用模板來解決它:

#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是解決歧義的“常用”方式 - 它始終按照您的期望行事,並且可以成為更大表達的一部分。

使用函數指針解析類型:

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

不要忘記包含<cctype> 演示

我將給出另外兩個解決方案來修復<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; })
  1. 使用顯式模板類型(您還需要編寫迭代器類型):

std::count_if<std::string::const_iterator, int(*)(int)>(s.begin(), s.end(), std::isdigit)

我發現以下也有效:

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

但我必須弄清楚它只有在C版本定義為函數而不是宏時才有效

因此,std :: isdigit的static_cast可能是平台中最好的便攜式解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM