2013-02-23 92 views
5

मैं सभी संख्याओं को स्ट्रिंग में सबसे कम कोड तरीके से गिनना चाहता हूं।स्ट्रिंग के साथ मानक एल्गोरिदम का उपयोग कर सी ++, 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 पता() चाहता है समारोह की तरह: मुझे लगता है कि जिस तरह से करने की कोशिश की bool (* च) (चार);

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) का उपयोग कैसे कर सकता हूं जो बूल (* एफ) (int) को एडाप्टर-फ़ंक्शंस के बिना और लैम्ब्डा एक्सप्रेशन का उपयोग किए बिना चाहते हैं?

मैं और अधिक मुद्दे हैं जो हल हो जाएगा जब मैं कैसे समस्या को हल करने को पता पाने के लिए है, उदाहरण के लिए:

  • जांच करें कि स्ट्रिंग प्रिंट करने योग्य है: find_if_not (s.begin(), s.end() , isprint)
  • जांच करें कि स्ट्रिंग है ", ...।!?": find_if (s.begin(), s.end(), ispunct) और बहुत कुछ ...

मैं बस मानक सी ++ में std :: एल्गोरिदमके लिए धन्यवाद और अधिक स्ट्रिंग संभावनाएं कैसे जानना चाहते हैंमैं इंटरनेट लंबे समय से खोज रहा था, मैं similar problem पाया, लेकिन मैं कोई समाधान

+0

त्रुटि पुन: पेश नहीं कर सकते, जी ++ 4.7.2 के साथ ठीक काम करता है (विन 7x64, मिनजीडब्ल्यू)। ** संपादित करें **: अगर मैं 'isdigit' के बजाय' std :: isdigit' का उपयोग करता हूं तो विफल रहता है। – Zeta

+0

यदि आप ' 'शीर्षलेख से फ़ंक्शंस के बारे में बात कर रहे हैं, तो वे सभी [एक' int 'लें और' int'] लौटें (http://en.cppreference.com/w/cpp/string/byte/isdigit) । – jrok

+0

एक फ़ंक्शन पास करना जो 'int' को एल्गोरिदम के पूर्वानुमान के रूप में देता है, कोई समस्या नहीं है। एल्गोरिदम उन परिचालनों के संदर्भ में निर्दिष्ट होते हैं जो वे लागू करते हैं, न कि उनके भविष्यवाणियों के हस्ताक्षर। यही है, 'अगर (एफ (एक्स)) ... '** ** ** ** की आवश्यकता नहीं है कि' एफ' वापसी 'बूल', केवल यह कि उसका रिटर्न प्रकार संदर्भित रूप से परिवर्तनीय 'बूल' हो। 'Int' का रिटर्न प्रकार यहां ठीक काम करता है। त्रुटि संदेश यह कह रहा है कि यह 'isdigit' के अधिभारित संस्करणों के बीच चयन नहीं कर सकता है, न कि 'isdigit' में गलत रिटर्न प्रकार है। –

उत्तर

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 

लेकिन मैं यह पता लगाने की है कि यह केवल तभी कारगर साबित सी संस्करण एक समारोह बजाय एक मैक्रो

के रूप में इस प्रकार परिभाषित किया गया है है, ठीक है, std :: isdigit का static_cast प्लेटफ़ॉर्म के बीच सबसे अच्छा पोर्टेबल समाधान हो सकता है।

0

मैं साथ <locale> std::isdigit

  1. उपयोग एक लैम्ब्डा अभिव्यक्ति अस्पष्टता ठीक करने के लिए 2 अन्य समाधान प्रदान करेंगे:

    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)

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^