2015-10-07 5 views
5

किसी स्ट्रिंग को देखते हुए एक संख्या का प्रतिनिधित्व करना चाहिए, मैं इसे एक रूपांतरण फ़ंक्शन में रखना चाहता हूं जो पूरे स्ट्रिंग को परिवर्तित नहीं किया गया है, तो अधिसूचना प्रदान करेगा।संपूर्ण स्ट्रिंग का उपभोग करने के लिए स्ट्रिंग को स्ट्रिंग को मजबूर करना

इनपुट के लिए: "12":

  • istringstream::operator>> आउटपुट 12
  • atoi आउटपुट 12
  • stoi आउटपुट 12

इनपुट "1X" के लिए मैं एक विफलता प्रतिसाद चाहते हैं, लेकिन मैं मिलता है:

  • istringstream::operator>> आउटपुट 1
  • atoi आउटपुट 1
  • stoi आउटपुट 1

इनपुट "X2" के लिए:

  • istringstream::operator>> आउटपुट 0 और एक त्रुटि ध्वज सेट
  • atoi आउटपुट 0
  • stoi एक त्रुटि फेंकता

[Live Example]

वहाँ इनपुट "1X" पर त्रुटि व्यवहार भड़काने के लिए कोई तरीका है?

+0

मुझे लगता है कि आपके पास SO में जवाब हैं: http://stackoverflow.com/questions/2844817/how-do-i-check-if-ac-string-is-an-int और http://stackoverflow.com/प्रश्न/1243428/कन्वर्ट-स्ट्रिंग-टू-इंट-बाय-बूल-असफल-इन-सी/1243435 # 1243435 – deepmax

+0

@ डिप्मैक्स यूप, कम से कम उदाहरण के प्रयोजनों के लिए मैंने इसे शामिल नहीं किया, लेकिन मेरे स्थानीय परीक्षण में कोड मैं इसे लूप के शीर्ष पर कर रहा हूं: 'cout <<" \ tinput स्ट्रिंग: "<< i << (all_of (i, i + strlen (i), बाइंड (isdigit, प्लेसहोल्डर :: _ 1)) ? "अच्छा है \ n": "खराब है \ n"); हालांकि, हालांकि, मैं इस तरह से जांच सकता हूं * मैं नहीं चाहता हूं। अन्य सभी कार्यों को प्रत्येक चरित्र के माध्यम से भी कदम उठाना चाहिए और मैं जो कुछ भी पहले से जानता हूं उसका उपयोग करने का एक तरीका बनाना चाहता हूं। –

+0

@ डिप्मैक्स आप गलत हैं यह डुप्लिकेट नहीं है, वे उत्तर ** ** ** यह सत्यापित नहीं करते हैं कि संपूर्ण स्ट्रिंग पढ़ी गई है। –

उत्तर

2

किसी दिए गए string str के लिए प्रत्येक को फायदे और नुकसान के साथ पूरा करने के कई तरीके हैं।

strtol

के रूप में सुझाव दिया herestrtol के बाहर पैरामीटर के पात्रों को पढ़ने के नंबर पाने के लिए इस्तेमाल किया जा सकता। strtol वास्तव में long पर int नहीं देता है, इसलिए वापसी पर एक कास्ट हो रहा है।

char* size; 
const int num = strtol(i.c_str(), &size, 10); 

if(distance(i.c_str(), const_cast<const char*>(size)) == i.size()) { 
    cout << "strtol: " << num << endl; 
} else { 
    cout << "strtol: error\n"; 
} 

ध्यान दें कि यह i.c_str() का उपयोग करता है एक ही स्ट्रिंग का उल्लेख करने के।c_str रिटर्न नहीं एक अस्थायी चरित्र भंडारण के रूप में सेवारत अंतर्निहित सरणी सूचक अगर आप सी ++ 11 है:

c_str() और data() एक ही समारोह में प्रदर्शन

भी ध्यान रखें कि सूचक c_str द्वारा दिया जाएगा strtol और distance कॉल के बीच मान्य हो, जब तक:

  • किसी भी मानक पुस्तकालय समारोह
  • string पर गैर const सदस्य कार्यों कॉलिंग, operator[], rbegin(), end() और rend()
छोड़कर at(), front(), back(), begin(), को string करने के लिए एक गैर const संदर्भ पासिंग

यदि आप इन मामलों में से किसी एक का उल्लंघन करते हैं तो आपको i के अंतर्निहित const char* की अस्थायी प्रतिलिपि बनाने की आवश्यकता होगी और उस पर परीक्षण करें।

sscanf

sscanf%n का उपयोग वर्णों की संख्या को पढ़ने के एक सूचक तुलना कर की तुलना में अधिक सहज ज्ञान युक्त हो सकता है वापस जाने के लिए कर सकते हैं। यदि आधार महत्वपूर्ण है, sscanf एक अच्छा विकल्प नहीं हो सकता है। strtol और stoi के विपरीत जो समर्थन 2 - 36, sscanf केवल ऑक्टल (%o), दशमलव (%d), और हेक्साडेसिमल (%x) के लिए विनिर्देशक प्रदान करता है।

size_t size; 
int num; 

if(sscanf(i.c_str(), "%d%n", &num, &size) == 1 && size == i.size()) { 
    cout << "sscanf: " << num << endl; 
} else { 
    cout << "sscanf: error\n"; 
} 

stoi

के रूप में सुझाव दिया herestoi रों %n के उत्पादन पैरामीटर sscanf तरह काम करता है 'नंबर लौटने के पात्रों पढ़ें। सी ++ को ध्यान में रखते हुए यह string लेता है और stoi से ऊपर सी कार्यान्वयन के विपरीत invalid_argument फेंकता है यदि पहले गैर-व्हाइटस्पेस वर्ण को वर्तमान आधार के लिए अंक नहीं माना जाता है, और दुर्भाग्य से इसका मतलब है कि सी कार्यान्वयन के विपरीत इसे एक त्रुटि की जांच करनी चाहिए try और catch दोनों ब्लॉक में।

try { 
    size_t size; 
    const auto num = stoi(i, &size); 

    if(size == i.size()) { 
     cout << "stoi: " << num << endl; 
    } else { 
     throw invalid_argument("invalid stoi argument"); 
    } 
} catch(const invalid_argument& /*e*/) { 
    cout << "stoi: error\n"; 
} 

[Live Example]

1

वैकल्पिक रूप से आप के रूप में आप का उल्लेख std::istringstream उपयोग करें, लेकिन यकीन है कि यह धारा के अंत में पार्स करने के लिए जाँच कर सकते हैं। मान लें कि आप एक निरंतर संदर्भ है, तो आप की तरह निम्नलिखित

T parse(const std::string& input) { 
    std::istringstream iss(input); 
     T result; 
     iss >> result; 
     if (iss.eof() || iss.tellg() == int(input.size())) { 
      return result; 
     } else { 
      throw std::invalid_argument("Couldn't parse entire string"); 
    } 
} 

इस दृष्टिकोण का लाभ कुछ कर सकते हैं कि आप कुछ भी है कि operator>> overloads पार्स है। नोट: यदि स्थिति पर्याप्त है, तो मुझे पूरी तरह से यकीन नहीं है, लेकिन मेरे परीक्षण के साथ ऐसा लगता है। कुछ कारणों से स्ट्रीम को अंत में पार्स करने में विफलता मिल जाएगी।

+0

मैंने आपको +1 दिया है क्योंकि यह किसी ऐसे व्यक्ति के लिए रूपांतरण करने का एक बहुत ही उपयोगी तरीका है जिसे 'आईटिंगस्ट्रीम' के साथ आगे काम करने की आवश्यकता है और आपके समाधान को शामिल कर सकता है, हालांकि सामान्य मामले में मुझे लगता है कि अधिक हल्के वजन में से एक [मेरे उत्तर] में रूपांतरण [http://stackoverflow.com/a/32997831/2642059) का उपयोग किया जाना चाहिए। –

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