C ++ में इंट को स्ट्रिंग कैसे पार्स करें?


261

एक int में एक स्ट्रिंग (चार के रूप में दिया जाता है) को पार्स करने का C ++ तरीका क्या है? मजबूत और स्पष्ट त्रुटि हैंडलिंग एक प्लस (बदले में शून्य ) है।


21
निम्नलिखित में से कुछ उदाहरणों के बारे में कैसे जानें : codeproject.com/KB/recipes/Tokenizer.aspx वे बहुत कुशल और कुछ हद तक सुरुचिपूर्ण हैं

@Beh Tou Cheh, अगर आपको लगता है कि यह int पार्स करने का एक अच्छा तरीका है, तो कृपया इसे उत्तर के रूप में पोस्ट करें।
यूजीन योकोटा

जवाबों:


165

नए C ++ 11 में इसके लिए कार्य हैं: stoi, stol, stoll, stoul इत्यादि।

int myNr = std::stoi(myString);

यह रूपांतरण त्रुटि पर एक अपवाद फेंक देगा।

यहां तक ​​कि इन नए कार्यों में अभी भी वही मुद्दा है जो डैन द्वारा नोट किया गया है: वे खुशी से स्ट्रिंग "11x" को पूर्णांक "11" में बदल देंगे।

और देखें: http://en.cppreference.com/w/cpp/string/basic_string/stol


4
लेकिन वे उस तर्क को स्वीकार करते हैं, उनमें से एक size_t के लिए एक बिंदु हो सकता है, अगर वह अशक्त नहीं है, तो पहले असंबद्ध चरित्र पर सेट है
Zharf

हां, std :: stoi के दूसरे पैरामीटर का उपयोग करके आप अमान्य इनपुट का पता लगा सकते हैं। आपको अभी भी अपने स्वयं के रूपांतरण फ़ंक्शन को रोल करना है ...
CC।

जैसे स्वीकार किए गए उत्तर ने किया, लेकिन इन मानक कार्यों के साथ जो ज्यादा साफ-सुथरा होगा, imo
Zharf

ध्यान रखें कि इन कार्यों में दूसरे तर्क का उपयोग यह बताने के लिए किया जा सकता है कि पूरे स्ट्रिंग को परिवर्तित किया गया था या नहीं। यदि परिणामस्वरूप size_tस्ट्रिंग की लंबाई के बराबर नहीं है, तो यह जल्दी बंद हो गया। यह उस स्थिति में अभी भी 11 लौटेगा, लेकिन posस्ट्रिंग की लंबाई के बजाय 2 होगा। coliru.stacked-croched.com/a/cabe25d64d2ffa29
Zoe

204

क्या नहीं कर सकते है

यहां मेरी सलाह का पहला टुकड़ा है: इसके लिए स्ट्रिंगस्ट्रीम का उपयोग न करें । हालांकि पहली बार में यह प्रयोग करने में सरल लग सकता है, आप पाएंगे कि अगर आप मजबूती और अच्छी त्रुटि से निपटना चाहते हैं तो आपको बहुत से अतिरिक्त काम करने होंगे।

यहाँ एक दृष्टिकोण है कि सहज ज्ञान युक्त लगता है जैसे यह काम करना चाहिए:

bool str2int (int &i, char const *s)
{
    std::stringstream ss(s);
    ss >> i;
    if (ss.fail()) {
        // not an integer
        return false;
    }
    return true;
}

यह एक बड़ी समस्या है: str2int(i, "1337h4x0r")खुशी से वापस आ जाएगी trueऔर iमूल्य प्राप्त करेगी 1337। हम इस समस्या को हल करने के stringstreamबाद यह सुनिश्चित कर सकते हैं कि रूपांतरण के बाद कोई और पात्र न हों :

bool str2int (int &i, char const *s)
{
    char              c;
    std::stringstream ss(s);
    ss >> i;
    if (ss.fail() || ss.get(c)) {
        // not an integer
        return false;
    }
    return true;
}

हमने एक समस्या को ठीक किया, लेकिन अभी भी कुछ समस्याएं हैं।

क्या होगा यदि स्ट्रिंग में संख्या 10 आधार नहीं है? हम ss << std::hexरूपांतरण की कोशिश करने से पहले स्ट्रीम को सही मोड (जैसे ) पर सेट करके अन्य आधारों को समायोजित करने का प्रयास कर सकते हैं । लेकिन इसका मतलब यह है कि फोन करने वाले को एक प्राथमिकता पता होनी चाहिए कि संख्या क्या आधार है - और कॉल करने वाला संभवतः यह कैसे जान सकता है? कॉल करने वाले को यह पता नहीं होता है कि नंबर क्या है। वे यह भी नहीं जानते कि यह हैएक संख्या! उनसे यह जानने की उम्मीद कैसे की जा सकती है कि इसका आधार क्या है? हम सिर्फ यह बता सकते हैं कि हमारे कार्यक्रमों के लिए सभी नंबरों के इनपुट का आधार 10 होना चाहिए और हेक्साडेसिमल या अष्टक इनपुट को अमान्य माना जाना चाहिए। लेकिन यह बहुत लचीला या मजबूत नहीं है। इस समस्या का कोई सरल उपाय नहीं है। आप प्रत्येक बेस के लिए एक बार रूपांतरण का प्रयास नहीं कर सकते, क्योंकि दशमलव रूपांतरण हमेशा ऑक्टल नंबरों (एक अग्रणी शून्य के साथ) के लिए सफल होगा और ऑक्टल रूपांतरण कुछ दशमलव नंबरों के लिए सफल हो सकता है। तो अब आपको एक अग्रणी शून्य की जांच करनी होगी। लेकिन रुकें! हेक्साडेसिमल संख्या एक प्रमुख शून्य के साथ भी शुरू हो सकती है (0x ...)। आह।

यहां तक ​​कि अगर आप उपरोक्त समस्याओं से निपटने में सफल होते हैं, तब भी एक और बड़ी समस्या है: क्या होगा यदि कॉल करने वाले को खराब इनपुट (जैसे "123foo") और एक संख्या के बीच अंतर करने की आवश्यकता होती है, जो की सीमा से बाहर है int(उदाहरण के लिए "4000000000") 32-बिट int)? के साथ stringstream, इस भेद को बनाने का कोई तरीका नहीं है। हम केवल यह जानते हैं कि रूपांतरण सफल हुआ या असफल। यदि यह विफल हो जाता है, तो हमारे पास यह जानने का कोई तरीका नहीं है कि यह विफल क्यों हुआ। जैसा कि आप देख सकते हैं, stringstreamअगर आप मजबूती और स्पष्ट त्रुटि से निपटने चाहते हैं तो वांछित होने के लिए बहुत कुछ छोड़ देता है।

सलाह की मेरी दूसरी टुकड़ा करने के लिए यह होता है मुझे: कोई फायदा नहीं बूस्ट है करना lexical_castइस बात के लिए । इस बात पर विचार करें कि lexical_castप्रलेखन का क्या कहना है:

जहाँ रूपांतरणों पर उच्च स्तर के नियंत्रण की आवश्यकता होती है, std :: stringstream and std :: wstringstream एक अधिक उपयुक्त मार्ग प्रदान करता है। जहां गैर-स्ट्रीम-आधारित रूपांतरणों की आवश्यकता होती है, lexical_cast नौकरी के लिए गलत उपकरण है और ऐसे परिदृश्यों के लिए विशेष-आवरण नहीं है।

क्या?? हम पहले ही देख चुके हैं कि stringstreamनियंत्रण का स्तर खराब है, और फिर भी यह कहता है कि यदि आपको "उच्च स्तर का नियंत्रण" stringstreamचाहिए, तो इसका उपयोग किया जाना चाहिए lexical_cast। इसके अलावा, क्योंकि lexical_castसिर्फ एक आवरण के आसपास है stringstream, यह वही समस्याओं से ग्रस्त है जो stringstreamकरता है: कई नंबर आधारों के लिए खराब समर्थन और खराब त्रुटि हैंडलिंग।

सबसे अच्छा समाधान

सौभाग्य से, किसी ने पहले ही उपरोक्त सभी समस्याओं को हल कर दिया है। C मानक लाइब्रेरी में strtolपरिवार और परिवार होते हैं जिनमें से कोई भी समस्या नहीं होती है।

enum STR2INT_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };

STR2INT_ERROR str2int (int &i, char const *s, int base = 0)
{
    char *end;
    long  l;
    errno = 0;
    l = strtol(s, &end, base);
    if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX) {
        return OVERFLOW;
    }
    if ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) {
        return UNDERFLOW;
    }
    if (*s == '\0' || *end != '\0') {
        return INCONVERTIBLE;
    }
    i = l;
    return SUCCESS;
}

किसी चीज के लिए बहुत आसान है जो सभी त्रुटि मामलों को संभालती है और 2 से 36 तक किसी भी संख्या के आधार का समर्थन करती है। यदि baseशून्य (डिफ़ॉल्ट) है तो यह किसी भी आधार से बदलने की कोशिश करेगा। या कॉल करने वाला तीसरे तर्क की आपूर्ति कर सकता है और निर्दिष्ट कर सकता है कि रूपांतरण केवल एक विशेष आधार के लिए किया जाना चाहिए। यह मजबूत है और कम से कम प्रयास के साथ सभी त्रुटियों को संभालता है।

पसंद करने के अन्य कारण strtol(और परिवार):

  • यह बहुत बेहतर रनटाइम प्रदर्शन प्रदर्शित करता है
  • यह कम संकलन-समय उपरि का परिचय देता है (अन्य हेडर से लगभग 20 गुना अधिक SLOC में खींचते हैं)
  • इसका परिणाम सबसे छोटे कोड आकार में होता है

किसी अन्य विधि का उपयोग करने का कोई अच्छा कारण नहीं है।


22
@JamesDunne: POSIX को strtolथ्रेड-सुरक्षित होना चाहिए । POSIX को errnoथ्रेड-लोकल स्टोरेज का भी उपयोग करना पड़ता है। गैर-पॉसिक्स सिस्टम पर भी, errnoमल्टीथ्रेड सिस्टम पर लगभग सभी कार्यान्वयन थ्रेड-लोकल स्टोरेज का उपयोग करते हैं। नवीनतम C ++ मानक को errnoPOSIX अनुरूप होना आवश्यक है। नवीनतम सी मानक के errnoलिए थ्रेड-लोकल स्टोरेज की भी आवश्यकता होती है। यहां तक ​​कि विंडोज पर, जो निश्चित रूप से पॉसिक्स कंप्लेंट नहीं है, errnoथ्रेड-सेफ है और, विस्तार से, ऐसा है strtol
दान मोल्डिंग

7
मैं वास्तव में बढ़ावा देने का उपयोग करने के खिलाफ अपने तर्क का पालन नहीं कर सकता :: lexical_cast। जैसा कि वे कहते हैं, std :: stringstream वास्तव में बहुत अधिक नियंत्रण प्रदान करता है - आप त्रुटि की जाँच से लेकर आधार निर्धारण तक सब कुछ करते हैं। वर्तमान दस्तावेज़ीकरण इसे इस तरह रखता है: "अधिक शामिल रूपांतरणों के लिए, जैसे कि जहां सटीक या स्वरूपण की आवश्यकता होती है, जहां lexical_cast के डिफ़ॉल्ट व्यवहार की पेशकश की जाती है, पारंपरिक std :: stringstream दृष्टिकोण की सिफारिश की जाती है।"
fhd

8
यह C ++ के भीतर अनुचित C कोडिंग है। इसके लिए मानक पुस्तकालय में std::stolहै, जो लगातार स्थिरांक के बजाय अपवादों को फेंक देगा।
fuzzyTew

22
@fuzzyTew मैंने यह उत्तर std::stolC ++ भाषा में जोड़े जाने से पहले लिखा था। उस ने कहा, मुझे नहीं लगता कि यह कहना उचित है कि यह "C ++ के भीतर कोडिंग" है। यह कहना मूर्खतापूर्ण है कि std::strtolसी कोडिंग है जब यह स्पष्ट रूप से सी ++ भाषा का हिस्सा है। मेरा उत्तर पूरी तरह से C ++ पर लागू होता है जब यह लिखा गया था और यह अभी भी नए के साथ लागू होता है std::stol। अपवादों को फेंकने वाले फ़ंक्शन को कॉल करना हमेशा हर प्रोग्रामिंग स्थिति के लिए सबसे अच्छा नहीं होता है।
दान मोल्डिंग

9
@fuzzyTew: डिस्क स्थान से बाहर निकलना एक असाधारण स्थिति है। विकृत डेटा फाइलें जो कंप्यूटर निर्मित हैं, एक असाधारण स्थिति हैं। लेकिन उपयोगकर्ता इनपुट में टाइपोस असाधारण नहीं हैं। एक पार्सिंग दृष्टिकोण होना अच्छा है जो सामान्य, गैर-असाधारण पार्सिंग विफलताओं को संभालने में सक्षम है।
बेन वोइगट

67

यह atoi की तुलना में एक सुरक्षित सी तरीका है ()

const char* str = "123";
int i;

if(sscanf(str, "%d", &i)  == EOF )
{
   /* error */
}

मानक लाइब्रेरी स्ट्रिंगस्ट्रीम के साथ C ++ : (धन्यवाद CMS )

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  if((ss >> num).fail())
  { 
      //ERROR 
  }
  return num;
}

बढ़ावा पुस्तकालय के साथ : (धन्यवाद jk )

#include <boost/lexical_cast.hpp>
#include <string>

try
{
    std::string str = "123";
    int number = boost::lexical_cast< int >( str );
}
catch( const boost::bad_lexical_cast & )
{
    // Error
}

संपादित करें: स्ट्रिंगस्ट्रीम संस्करण को ठीक किया ताकि वह त्रुटियों को संभाल सके। (मूल पोस्ट पर CMS और jk की टिप्पणी के लिए धन्यवाद)


1
स्ट्रिंगस्ट्रीम के लिए एक चेक शामिल करने के लिए कृपया अपने स्ट्रिंगस्ट्रीम संस्करण को अपडेट करें :: असफल () (जैसा कि प्रश्नकर्ता "रोबस्ट और स्पष्ट त्रुटि हैंडलिंग" द्वारा अनुरोध किया गया है)
jk।

2
आपका stringstream संस्करण "10haha" की तरह सामान को स्वीकार करेंगे शिकायत के बिना
litb - Johannes Schaub

3
इसे ((ss >> num) .fail () और& (ss >> ws) .eof ()) से ((ss >> num) .fail ()) में बदलें, यदि आप lexical -cast
जोहान्स की

3
मानक लाइब्रेरी स्ट्रिंगस्ट्रीम विधि के साथ C ++, .fail () चेक के साथ भी "12-SomeString" जैसे तारों के लिए काम नहीं करता है।
captonssj

C ++ 11 में अब इसके लिए मानक तेज कार्य शामिल हैं
fuzzyTew

21

अच्छा 'पुराना सी रास्ता अभी भी काम करता है। मैं स्ट्रेटोल या स्ट्रैटोल की सलाह देता हूं। रिटर्न की स्थिति और 'एंडप्राट' के बीच, आप अच्छे डायग्नोस्टिक आउटपुट दे सकते हैं। यह भी कई ठिकानों को अच्छी तरह से संभालता है।


4
ओह कृपया इस पुराने सी सामान का उपयोग न करें जब प्रोग्रामिंग सी ++। C ++ में ऐसा करने के लिए बेहतर / आसान / क्लीनर / अधिक आधुनिक / सुरक्षित तरीके हैं!
जे.के.

27
यह हास्यास्पद है जब लोग किसी समस्या को हल करने के "अधिक आधुनिक" तरीकों के बारे में चिंतित होते हैं।
जे मिलर

@ जैसन, IMO मजबूत प्रकार की सुरक्षा और एरर हैंडलिंग सी की तुलना में अधिक आधुनिक विचार है
यूजीन योकोटा

6
मैंने अन्य उत्तरों को देखा है, और अभी तक कुछ भी स्पष्ट रूप से बेहतर / आसान / क्लीनर या सुरक्षित नहीं है। पोस्टर में कहा गया है कि उसके पास एक चार * था। उस सुरक्षा की मात्रा को सीमित करता है जो आप पाने जा रहे हैं :)
क्रिस अरगिन

21

आप बूस्ट काlexical_cast उपयोग कर सकते हैं , जो इसे अधिक सामान्य इंटरफ़ेस में लपेटता है। असफलता पर lexical_cast<Target>(Source)फेंकता bad_lexical_castहै।


12
बूस्ट लेक्सिकल_कास्ट बेहद धीमा और दर्द रहित है।

3
@Matthieu Boost के अपडेट ने प्रदर्शन में काफी सुधार किया है: boost.org/doc/libs/1_49_0/doc/html/boost_lexical_cast/… (भी देखें stackoverflow.com/questions/1250795/… )
मक्खियाँ

16

आप C ++ मानक लाइब्रेरै से एक स्ट्रिंगस्ट्रीम का उपयोग कर सकते हैं:

stringstream ss(str);
int x;
ss >> x;

if(ss) { // <-- error handling
  // use x
} else {
  // not a number
}

यदि कोई पूर्णांक पढ़ने की कोशिश कर रहा है, तो एक गैर-अंक का सामना करने पर स्ट्रीम राज्य विफल हो जाएगा।

सी ++ में त्रुटि और धाराओं के नुकसान के लिए स्ट्रीम नुकसान देखें ।


2
C ++ स्ट्रिंगस्ट्रीम विधि "12-SomeString" जैसे स्ट्रिंग्स के लिए भी काम नहीं करता है, यहां तक ​​कि 'स्ट्रीम स्टेट' चेक के साथ भी।
captonssj

10

आप स्ट्रिंगस्ट्रीम का उपयोग कर सकते हैं

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  ss >> num;
  return num;
}

4
लेकिन इससे कोई त्रुटि नहीं होती है। आपको विफलताओं के लिए स्ट्रीम की जांच करनी होगी।
जे.के.

1
ठीक है तुम धारा जाँच करने के लिए है ((एस एस >> संख्या) .fail ()) {// ERROR}
सीएमएस

2
C ++ स्ट्रिंगस्ट्रीम विधि "12-SomeString" जैसे स्ट्रिंग्स के लिए भी काम नहीं करती है, यहां तक ​​कि 'स्ट्रीम स्टेट' चेक के साथ भी
captonssj

8

मुझे लगता है कि ये तीन लिंक इसे जोड़ते हैं:

stringstream और lexical_cast समाधान उसी के बारे में हैं जैसे lexical कास्ट stringstream का उपयोग कर रहा है।

लेक्सिकल कास्ट के कुछ विशेषज्ञ अलग दृष्टिकोण का उपयोग करते हैं http://www.boost.org/doc/libs/release/boost/lexical_cast.hpp , विवरण के लिए देखें। पूर्णांक से स्ट्रिंग रूपांतरण में पूर्णांक के लिए अब इंटीग्रेटर और फ्लोट्स विशिष्ट हैं।

एक अपनी जरूरतों के लिए lexical_cast विशेषज्ञ कर सकता है और इसे तेजी से बना सकता है। स्वच्छ और सरल सभी पक्षों को संतुष्ट करने वाला यह अंतिम समाधान होगा।

पहले से ही उल्लेख किए गए लेख पूर्णांक को परिवर्तित करने के विभिन्न तरीकों के बीच शो की तुलना <-> तार। निम्नलिखित दृष्टिकोण समझ में आते हैं: पुराने सी-वे, स्पिरिट। कर्म, फास्टफॉर्म, सरल भोले पाश।

लेक्सिकल_कास्ट कुछ मामलों में ठीक है, उदाहरण के लिए स्ट्रिंग से रूपांतरण के लिए।

लेक्सिकल कास्ट का उपयोग करने के लिए स्ट्रिंग को परिवर्तित करना एक अच्छा विचार नहीं है क्योंकि यह प्लेटफॉर्म / कंपाइलर के आधार पर एटॉय की तुलना में 10-40 गुना धीमा है।

Boost.Spirit.Karma पूर्णांक को स्ट्रिंग में परिवर्तित करने के लिए सबसे तेज़ पुस्तकालय प्रतीत होता है।

ex.: generate(ptr_char, int_, integer_number);

और ऊपर उल्लिखित लेख से बुनियादी सरल लूप को स्ट्रिंग को इंट में बदलने का सबसे तेज़ तरीका है, जाहिर है कि सबसे सुरक्षित नहीं है, स्ट्रटोल () एक सुरक्षित समाधान की तरह लगता है

int naive_char_2_int(const char *p) {
    int x = 0;
    bool neg = false;
    if (*p == '-') {
        neg = true;
        ++p;
    }
    while (*p >= '0' && *p <= '9') {
        x = (x*10) + (*p - '0');
        ++p;
    }
    if (neg) {
        x = -x;
    }
    return x;
}

7

सी ++ स्ट्रिंग टूलकिट लाइब्रेरी (StrTk) निम्नलिखित समाधान है:

static const std::size_t digit_table_symbol_count = 256;
static const unsigned char digit_table[digit_table_symbol_count] = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF - 0x07
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x08 - 0x0F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10 - 0x17
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x18 - 0x1F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x20 - 0x27
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x28 - 0x2F
   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37
   0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x38 - 0x3F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x40 - 0x47
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x48 - 0x4F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x50 - 0x57
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x58 - 0x5F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x60 - 0x67
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x68 - 0x6F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x70 - 0x77
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x78 - 0x7F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x80 - 0x87
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x88 - 0x8F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x90 - 0x97
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x98 - 0x9F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA0 - 0xA7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA8 - 0xAF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB0 - 0xB7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB8 - 0xBF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC0 - 0xC7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC8 - 0xCF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD0 - 0xD7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD8 - 0xDF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE0 - 0xE7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE8 - 0xEF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xF0 - 0xF7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // 0xF8 - 0xFF
 };

template<typename InputIterator, typename T>
inline bool string_to_signed_type_converter_impl_itr(InputIterator begin, InputIterator end, T& v)
{
   if (0 == std::distance(begin,end))
      return false;
   v = 0;
   InputIterator it = begin;
   bool negative = false;
   if ('+' == *it)
      ++it;
   else if ('-' == *it)
   {
      ++it;
      negative = true;
   }
   if (end == it)
      return false;
   while(end != it)
   {
      const T digit = static_cast<T>(digit_table[static_cast<unsigned int>(*it++)]);
      if (0xFF == digit)
         return false;
      v = (10 * v) + digit;
   }
   if (negative)
      v *= -1;
   return true;
}

InputIterator या तो अहस्ताक्षरित char *, char * या std :: string iterators का हो सकता है, और T से एक हस्ताक्षरित int होने की उम्मीद की जाती है, जैसे कि हस्ताक्षरित int, int, या लंबे समय तक।


1
चेतावनी यह कार्यान्वयन अच्छा लग रहा है, लेकिन जहाँ तक मैं बता सकता हूँ कि यह ज़रूरत से ज़्यादा नहीं है।
विन्नी फाल्को

2
कोड अतिप्रवाह नहीं संभालता है। v = (10 * v) + digit;के मूल पाठ के साथ स्ट्रिंग इनपुट के साथ अनावश्यक जरूरत से ज्यादा INT_MIN। तालिका संदिग्ध मूल्य बनाम बस हैdigit >= '0' && digit <= '9'
chux -

6

आप सी ++ 11 है, तो उपयुक्त समाधान आजकल सी ++ में रूपांतरण कार्यों पूर्णांक हैं <string>: stoi, stol, stoul, stoll, stoull। गलत इनपुट दिए जाने पर वे उपयुक्त अपवादों को फेंक देते हैं और strto*हुड के नीचे तेज और छोटे कार्यों का उपयोग करते हैं ।

यदि आप C ++ के पहले के संशोधन के साथ फंस गए हैं, तो आपके कार्यान्वयन में इन कार्यों की नकल करना आपके लिए आगे-पोर्टेबल होगा।


6

C ++ से 17 के बाद आप उपयोग कर सकते हैं std::from_charsसे <charconv>शीर्ष लेख के रूप में दस्तावेज यहां

उदाहरण के लिए:

#include <iostream>
#include <charconv>
#include <array>

int main()
{
    char const * str = "42";
    int value = 0;

    std::from_chars_result result = std::from_chars(std::begin(str), std::end(str), value);

    if(result.error == std::errc::invalid_argument)
    {
      std::cout << "Error, invalid format";
    }
    else if(result.error == std::errc::result_out_of_range)
    {
      std::cout << "Error, value too big for int range";
    }
    else
    {
      std::cout << "Success: " << result;
    }
}

एक बोनस के रूप में, यह हेक्साडेसिमल की तरह अन्य ठिकानों को भी संभाल सकता है।


3

मुझे डैन मोल्डिंग का जवाब पसंद है , मैं इसमें केवल C ++ शैली का एक सा जोड़ दूंगा:

#include <cstdlib>
#include <cerrno>
#include <climits>
#include <stdexcept>

int to_int(const std::string &s, int base = 0)
{
    char *end;
    errno = 0;
    long result = std::strtol(s.c_str(), &end, base);
    if (errno == ERANGE || result > INT_MAX || result < INT_MIN)
        throw std::out_of_range("toint: string is out of range");
    if (s.length() == 0 || *end != '\0')
        throw std::invalid_argument("toint: invalid string");
    return result;
}

यह अंतर्निहित रूपांतरण के माध्यम से std :: string और const char * दोनों के लिए काम करता है। यह भी आधार रूपांतरण के लिए उपयोगी है, उदाहरण के लिए सभी to_int("0x7b")और to_int("0173")और to_int("01111011", 2)और to_int("0000007B", 16)और to_int("11120", 3)और to_int("3L", 34);123 लौट आते हैं।

इसके विपरीत std::stoiयह पूर्व-सी ++ 11 में काम करता है। इसके विपरीत std::stoi, boost::lexical_castऔर stringstreamयह "123hohoho" जैसे अजीब तार के लिए अपवाद फेंकता है।

नायब: यह फ़ंक्शन प्रमुख स्थानों को सहन करता है, लेकिन रिक्त स्थान को नहीं छोड़ता है, अर्थात अपवाद को to_int(" 123")फेंकते समय 123 लौटाता to_int("123 ")है। सुनिश्चित करें कि यह आपके उपयोग के मामले के लिए स्वीकार्य है या कोड समायोजित करें।

इस तरह का समारोह STL का हिस्सा हो सकता है ...


2

मैं स्ट्रिंग को इंट में बदलने के तीन तरीके जानता हूं:

या तो stoi का उपयोग करें (String to int) फ़ंक्शन या बस Stringstream के साथ जाने के लिए, व्यक्तिगत रूपांतरण जाने का तीसरा तरीका, कोड नीचे है:

पहली विधि

std::string s1 = "4533";
std::string s2 = "3.010101";
std::string s3 = "31337 with some string";

int myint1 = std::stoi(s1);
int myint2 = std::stoi(s2);
int myint3 = std::stoi(s3);

std::cout <<  s1 <<"=" << myint1 << '\n';
std::cout <<  s2 <<"=" << myint2 << '\n';
std::cout <<  s3 <<"=" << myint3 << '\n';

दूसरी विधि

#include <string.h>
#include <sstream>
#include <iostream>
#include <cstring>
using namespace std;


int StringToInteger(string NumberAsString)
{
    int NumberAsInteger;
    stringstream ss;
    ss << NumberAsString;
    ss >> NumberAsInteger;
    return NumberAsInteger;
}
int main()
{
    string NumberAsString;
    cin >> NumberAsString;
    cout << StringToInteger(NumberAsString) << endl;
    return 0;
} 

3 विधि - लेकिन एक व्यक्तिगत रूपांतरण के लिए नहीं

std::string str4 = "453";
int i = 0, in=0; // 453 as on
for ( i = 0; i < str4.length(); i++)
{

    in = str4[i];
    cout <<in-48 ;

}

1

मुझे डैन का जवाब पसंद है , अपवादों से बचने के कारण जासूसी। एम्बेडेड सिस्टम डेवलपमेंट और अन्य निम्न स्तर सिस्टम डेवलपमेंट के लिए, एक उचित अपवाद फ्रेमवर्क उपलब्ध नहीं हो सकता है।

एक वैध स्ट्रिंग के बाद सफेद-स्थान के लिए एक चेक जोड़ा ... इन तीन पंक्तियों

    while (isspace(*end)) {
        end++;
    }


पार्सिंग त्रुटियों के लिए एक चेक भी जोड़ा।

    if ((errno != 0) || (s == end)) {
        return INCONVERTIBLE;
    }


यहां देखें पूरा समारोह ..

#include <cstdlib>
#include <cerrno>
#include <climits>
#include <stdexcept>

enum STR2INT_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };

STR2INT_ERROR str2long (long &l, char const *s, int base = 0)
{
    char *end = (char *)s;
    errno = 0;

    l = strtol(s, &end, base);

    if ((errno == ERANGE) && (l == LONG_MAX)) {
        return OVERFLOW;
    }
    if ((errno == ERANGE) && (l == LONG_MIN)) {
        return UNDERFLOW;
    }
    if ((errno != 0) || (s == end)) {
        return INCONVERTIBLE;
    }    
    while (isspace((unsigned char)*end)) {
        end++;
    }

    if (*s == '\0' || *end != '\0') {
        return INCONVERTIBLE;
    }

    return SUCCESS;
}

@chux ने आपके द्वारा बताई गई चिंताओं का ध्यान रखने के लिए कोड जोड़ा।
पीलूसीड

1) अभी भी इनपुट की तरह त्रुटि का पता लगाने में विफल रहता है " "। कोई रूपांतरण नहीं होने strtol()पर सेट करने के लिए निर्दिष्ट errnoनहीं है। if (s == end) return INCONVERTIBLE; रूपांतरण न करने के लिए उपयोग करने के लिए बेहतर है । और फिर 2 if (*s == '\0' || *end != '\0')को सरल कर सकते हैं if (*end)) || l > LONG_MAXऔर || l < LONG_MINबिना किसी उद्देश्य के सेवा कर सकते हैं - वे कभी सच नहीं होते हैं।
चक्स - मोनिका

@chux एक मैक पर, त्रुटी को पार्स करने की त्रुटियों के लिए सेट किया गया है, लेकिन लिनक्स पर इरनो सेट नहीं है। पता लगाने के लिए "अंत" सूचक पर निर्भर करने के लिए परिवर्तित कोड।
पेल्यूसाइड

0

आप इस परिभाषित विधि का उपयोग कर सकते हैं।

#define toInt(x) {atoi(x.c_str())};

और यदि आप String से एक Integer में कन्वर्ट करने के लिए थे, तो आप बस निम्नलिखित करेंगे।

int main()
{
string test = "46", test2 = "56";
int a = toInt(test);
int b = toInt(test2);
cout<<a+b<<endl;
}

आउटपुट 102 होगा।


4
idk। चारों ओर एक परिभाषित मैक्रो लिखना atoi"सी + + रास्ता" की तरह प्रतीत नहीं होता है, स्वीकार किए जाते हैं जैसे अन्य उत्तरों के प्रकाश में std::stoi()
यूजीन योकोटा

मुझे पूर्व-परिभाषित तरीकों का उपयोग करके यह अधिक मजेदार लगता है: पी
बोरिस

0

मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैं इसके बारे में कई बार और आज तक आया हूं, फिर भी निम्नलिखित विशेषताओं वाले एक अच्छी तरह से टेम्पर्ड समाधान नहीं मिला है:

  • किसी भी आधार को बदल सकते हैं (और आधार प्रकार का पता लगा सकते हैं)
  • त्रुटिपूर्ण डेटा का पता लगाएगा (अर्थात संपूर्ण स्ट्रिंग, कम प्रमुख / अनुगामी व्हाट्सएप, रूपांतरण द्वारा भस्म हो जाता है)
  • यह सुनिश्चित करेगा कि परिवर्तित प्रकार की परवाह किए बिना, स्ट्रिंग के मूल्य की सीमा स्वीकार्य है।

तो, यहाँ मेरा है, एक परीक्षण पट्टा के साथ। क्योंकि यह हुड के नीचे C फंक्शंस strtoull / strtoll का उपयोग करता है, यह हमेशा सबसे पहले उपलब्ध सबसे बड़े प्रकार में परिवर्तित होता है। फिर, यदि आप सबसे बड़े प्रकार का उपयोग नहीं कर रहे हैं, तो यह सत्यापित करने के लिए अतिरिक्त रेंज जाँच करेगा कि आपका प्रकार खत्म नहीं हुआ था (नीचे) प्रवाहित नहीं हुआ था। इसके लिए, यह थोड़ा कम परफ़ॉर्मेंट है, अगर कोई ठीक से स्ट्रेटोल / स्ट्रेटोल चुनता है। हालांकि, यह शॉर्ट्स / चार्ट के लिए भी काम करता है और, मेरे ज्ञान के सर्वश्रेष्ठ के लिए, कोई मानक लाइब्रेरी फ़ंक्शन मौजूद नहीं है जो ऐसा भी करता है।

का आनंद लें; उम्मीद है कि कोई इसे उपयोगी पाता है।

#include <cstdlib>
#include <cerrno>
#include <limits>
#include <stdexcept>
#include <sstream>

static const int DefaultBase = 10;

template<typename T>
static inline T CstrtoxllWrapper(const char *str, int base = DefaultBase)
{
    while (isspace(*str)) str++; // remove leading spaces; verify there's data
    if (*str == '\0') { throw std::invalid_argument("str; no data"); } // nothing to convert

    // NOTE:  for some reason strtoull allows a negative sign, we don't; if
    //          converting to an unsigned then it must always be positive!
    if (!std::numeric_limits<T>::is_signed && *str == '-')
    { throw std::invalid_argument("str; negative"); }

    // reset errno and call fn (either strtoll or strtoull)
    errno = 0;
    char *ePtr;
    T tmp = std::numeric_limits<T>::is_signed ? strtoll(str, &ePtr, base)
                                              : strtoull(str, &ePtr, base);

    // check for any C errors -- note these are range errors on T, which may
    //   still be out of the range of the actual type we're using; the caller
    //   may need to perform additional range checks.
    if (errno != 0) 
    {
            if (errno == ERANGE) { throw std::range_error("str; out of range"); }
            else if (errno == EINVAL) { throw std::invalid_argument("str; EINVAL"); }
            else { throw std::invalid_argument("str; unknown errno"); }
    }

    // verify everything converted -- extraneous spaces are allowed
    if (ePtr != NULL)
    {
            while (isspace(*ePtr)) ePtr++;
            if (*ePtr != '\0') { throw std::invalid_argument("str; bad data"); }
    }

    return tmp;
}

template<typename T>
T StringToSigned(const char *str, int base = DefaultBase)
{
    static const long long max = std::numeric_limits<T>::max();
    static const long long min = std::numeric_limits<T>::min();

    long long tmp = CstrtoxllWrapper<typeof(tmp)>(str, base); // use largest type

    // final range check -- only needed if not long long type; a smart compiler
    //   should optimize this whole thing out
    if (sizeof(T) == sizeof(tmp)) { return tmp; }

    if (tmp < min || tmp > max)
    {
            std::ostringstream err;
            err << "str; value " << tmp << " out of " << sizeof(T) * 8
                << "-bit signed range (";
            if (sizeof(T) != 1) err << min << ".." << max;
            else err << (int) min << ".." << (int) max;  // don't print garbage chars
            err << ")";
            throw std::range_error(err.str());
    }

    return tmp;
}

template<typename T>
T StringToUnsigned(const char *str, int base = DefaultBase)
{
    static const unsigned long long max = std::numeric_limits<T>::max();

    unsigned long long tmp = CstrtoxllWrapper<typeof(tmp)>(str, base); // use largest type

    // final range check -- only needed if not long long type; a smart compiler
    //   should optimize this whole thing out
    if (sizeof(T) == sizeof(tmp)) { return tmp; }

    if (tmp > max)
    {
            std::ostringstream err;
            err << "str; value " << tmp << " out of " << sizeof(T) * 8
                << "-bit unsigned range (0..";
            if (sizeof(T) != 1) err << max;
            else err << (int) max;  // don't print garbage chars
            err << ")";
            throw std::range_error(err.str());
    }

    return tmp;
}

template<typename T>
inline T
StringToDecimal(const char *str, int base = DefaultBase)
{
    return std::numeric_limits<T>::is_signed ? StringToSigned<T>(str, base)
                                             : StringToUnsigned<T>(str, base);
}

template<typename T>
inline T
StringToDecimal(T &out_convertedVal, const char *str, int base = DefaultBase)
{
    return out_convertedVal = StringToDecimal<T>(str, base);
}

/*============================== [ Test Strap ] ==============================*/ 

#include <inttypes.h>
#include <iostream>

static bool _g_anyFailed = false;

template<typename T>
void TestIt(const char *tName,
            const char *s, int base,
            bool successExpected = false, T expectedValue = 0)
{
    #define FAIL(s) { _g_anyFailed = true; std::cout << s; }

    T x;
    std::cout << "converting<" << tName << ">b:" << base << " [" << s << "]";
    try
    {
            StringToDecimal<T>(x, s, base);
            // get here on success only
            if (!successExpected)
            {
                    FAIL(" -- TEST FAILED; SUCCESS NOT EXPECTED!" << std::endl);
            }
            else
            {
                    std::cout << " -> ";
                    if (sizeof(T) != 1) std::cout << x;
                    else std::cout << (int) x;  // don't print garbage chars
                    if (x != expectedValue)
                    {
                            FAIL("; FAILED (expected value:" << expectedValue << ")!");
                    }
                    std::cout << std::endl;
            }
    }
    catch (std::exception &e)
    {
            if (successExpected)
            {
                    FAIL(   " -- TEST FAILED; EXPECTED SUCCESS!"
                         << " (got:" << e.what() << ")" << std::endl);
            }
            else
            {
                    std::cout << "; expected exception encounterd: [" << e.what() << "]" << std::endl;
            }
    }
}

#define TEST(t, s, ...) \
    TestIt<t>(#t, s, __VA_ARGS__);

int main()
{
    std::cout << "============ variable base tests ============" << std::endl;
    TEST(int, "-0xF", 0, true, -0xF);
    TEST(int, "+0xF", 0, true, 0xF);
    TEST(int, "0xF", 0, true, 0xF);
    TEST(int, "-010", 0, true, -010);
    TEST(int, "+010", 0, true, 010);
    TEST(int, "010", 0, true, 010);
    TEST(int, "-10", 0, true, -10);
    TEST(int, "+10", 0, true, 10);
    TEST(int, "10", 0, true, 10);

    std::cout << "============ base-10 tests ============" << std::endl;
    TEST(int, "-010", 10, true, -10);
    TEST(int, "+010", 10, true, 10);
    TEST(int, "010", 10, true, 10);
    TEST(int, "-10", 10, true, -10);
    TEST(int, "+10", 10, true, 10);
    TEST(int, "10", 10, true, 10);
    TEST(int, "00010", 10, true, 10);

    std::cout << "============ base-8 tests ============" << std::endl;
    TEST(int, "777", 8, true, 0777);
    TEST(int, "-0111 ", 8, true, -0111);
    TEST(int, "+0010 ", 8, true, 010);

    std::cout << "============ base-16 tests ============" << std::endl;
    TEST(int, "DEAD", 16, true, 0xDEAD);
    TEST(int, "-BEEF", 16, true, -0xBEEF);
    TEST(int, "+C30", 16, true, 0xC30);

    std::cout << "============ base-2 tests ============" << std::endl;
    TEST(int, "-10011001", 2, true, -153);
    TEST(int, "10011001", 2, true, 153);

    std::cout << "============ irregular base tests ============" << std::endl;
    TEST(int, "Z", 36, true, 35);
    TEST(int, "ZZTOP", 36, true, 60457993);
    TEST(int, "G", 17, true, 16);
    TEST(int, "H", 17);

    std::cout << "============ space deliminated tests ============" << std::endl;
    TEST(int, "1337    ", 10, true, 1337);
    TEST(int, "   FEAD", 16, true, 0xFEAD);
    TEST(int, "   0711   ", 0, true, 0711);

    std::cout << "============ bad data tests ============" << std::endl;
    TEST(int, "FEAD", 10);
    TEST(int, "1234 asdfklj", 10);
    TEST(int, "-0xF", 10);
    TEST(int, "+0xF", 10);
    TEST(int, "0xF", 10);
    TEST(int, "-F", 10);
    TEST(int, "+F", 10);
    TEST(int, "12.4", 10);
    TEST(int, "ABG", 16);
    TEST(int, "10011002", 2);

    std::cout << "============ int8_t range tests ============" << std::endl;
    TEST(int8_t, "7F", 16, true, std::numeric_limits<int8_t>::max());
    TEST(int8_t, "80", 16);
    TEST(int8_t, "-80", 16, true, std::numeric_limits<int8_t>::min());
    TEST(int8_t, "-81", 16);
    TEST(int8_t, "FF", 16);
    TEST(int8_t, "100", 16);

    std::cout << "============ uint8_t range tests ============" << std::endl;
    TEST(uint8_t, "7F", 16, true, std::numeric_limits<int8_t>::max());
    TEST(uint8_t, "80", 16, true, std::numeric_limits<int8_t>::max()+1);
    TEST(uint8_t, "-80", 16);
    TEST(uint8_t, "-81", 16);
    TEST(uint8_t, "FF", 16, true, std::numeric_limits<uint8_t>::max());
    TEST(uint8_t, "100", 16);

    std::cout << "============ int16_t range tests ============" << std::endl;
    TEST(int16_t, "7FFF", 16, true, std::numeric_limits<int16_t>::max());
    TEST(int16_t, "8000", 16);
    TEST(int16_t, "-8000", 16, true, std::numeric_limits<int16_t>::min());
    TEST(int16_t, "-8001", 16);
    TEST(int16_t, "FFFF", 16);
    TEST(int16_t, "10000", 16);

    std::cout << "============ uint16_t range tests ============" << std::endl;
    TEST(uint16_t, "7FFF", 16, true, std::numeric_limits<int16_t>::max());
    TEST(uint16_t, "8000", 16, true, std::numeric_limits<int16_t>::max()+1);
    TEST(uint16_t, "-8000", 16);
    TEST(uint16_t, "-8001", 16);
    TEST(uint16_t, "FFFF", 16, true, std::numeric_limits<uint16_t>::max());
    TEST(uint16_t, "10000", 16);

    std::cout << "============ int32_t range tests ============" << std::endl;
    TEST(int32_t, "7FFFFFFF", 16, true, std::numeric_limits<int32_t>::max());
    TEST(int32_t, "80000000", 16);
    TEST(int32_t, "-80000000", 16, true, std::numeric_limits<int32_t>::min());
    TEST(int32_t, "-80000001", 16);
    TEST(int32_t, "FFFFFFFF", 16);
    TEST(int32_t, "100000000", 16);

    std::cout << "============ uint32_t range tests ============" << std::endl;
    TEST(uint32_t, "7FFFFFFF", 16, true, std::numeric_limits<int32_t>::max());
    TEST(uint32_t, "80000000", 16, true, std::numeric_limits<int32_t>::max()+1);
    TEST(uint32_t, "-80000000", 16);
    TEST(uint32_t, "-80000001", 16);
    TEST(uint32_t, "FFFFFFFF", 16, true, std::numeric_limits<uint32_t>::max());
    TEST(uint32_t, "100000000", 16);

    std::cout << "============ int64_t range tests ============" << std::endl;
    TEST(int64_t, "7FFFFFFFFFFFFFFF", 16, true, std::numeric_limits<int64_t>::max());
    TEST(int64_t, "8000000000000000", 16);
    TEST(int64_t, "-8000000000000000", 16, true, std::numeric_limits<int64_t>::min());
    TEST(int64_t, "-8000000000000001", 16);
    TEST(int64_t, "FFFFFFFFFFFFFFFF", 16);
    TEST(int64_t, "10000000000000000", 16);

    std::cout << "============ uint64_t range tests ============" << std::endl;
    TEST(uint64_t, "7FFFFFFFFFFFFFFF", 16, true, std::numeric_limits<int64_t>::max());
    TEST(uint64_t, "8000000000000000", 16, true, std::numeric_limits<int64_t>::max()+1);
    TEST(uint64_t, "-8000000000000000", 16);
    TEST(uint64_t, "-8000000000000001", 16);
    TEST(uint64_t, "FFFFFFFFFFFFFFFF", 16, true, std::numeric_limits<uint64_t>::max());
    TEST(uint64_t, "10000000000000000", 16);

    std::cout << std::endl << std::endl
              << (_g_anyFailed ? "!! SOME TESTS FAILED !!" : "ALL TESTS PASSED")
              << std::endl;

    return _g_anyFailed;
}

StringToDecimalउपयोगकर्ता-भूमि विधि है; यह अतिभारित है इसलिए इसे इस तरह कहा जा सकता है:

int a; a = StringToDecimal<int>("100");

या यह:

int a; StringToDecimal(a, "100");

मुझे इंट के प्रकार को दोहराने से नफरत है, इसलिए बाद वाले को पसंद करते हैं। यह सुनिश्चित करता है कि यदि one a ’के प्रकार में परिवर्तन होता है तो बुरे परिणाम नहीं मिलते हैं। मैं चाहता हूँ संकलक यह समझ सकता है:

int a; a = StringToDecimal("100");

... लेकिन, C ++ टेम्पलेट रिटर्न प्रकार नहीं घटाता है, इसलिए यह सबसे अच्छा है जो मुझे मिल सकता है।

कार्यान्वयन बहुत सरल है:

CstrtoxllWrapperटेम्प्लेट प्रकार के हस्ताक्षरित-नेस के आधार पर जो भी आवश्यक हो, दोनों को लपेटता है strtoullऔर strtollकुछ अतिरिक्त गारंटी प्रदान करता है (जैसे यदि अहस्ताक्षरित होने पर नकारात्मक इनपुट अस्वीकृत हो जाता है और यह सुनिश्चित करता है कि संपूर्ण स्ट्रिंग परिवर्तित हो गया था)।

CstrtoxllWrapperद्वारा किया जाता है StringToSignedऔर StringToUnsignedसबसे बड़ा प्रकार (लंबे / लंबे अहस्ताक्षरित) संकलक के लिए उपलब्ध के साथ; यह अधिकतम रूपांतरण करने की अनुमति देता है। फिर, यदि यह आवश्यक है, StringToSigned/ StringToUnsignedअंतर्निहित प्रकार पर अंतिम श्रेणी की जांच करता है। अंत में, अंत-बिंदु विधि, यह StringToDecimalतय करती है कि अंतर्निहित प्रकार के हस्ताक्षरित नेस के आधार पर कॉल करने के लिए स्ट्रिंगिंगो * टेम्पलेट विधियों में से कौन सा है।

मुझे लगता है कि अधिकांश कबाड़ को संकलक द्वारा अनुकूलित किया जा सकता है; बस के बारे में सब कुछ संकलन-समय निर्धारक होना चाहिए। इस पहलू पर कोई भी टिप्पणी मेरे लिए दिलचस्प होगी!


"सबसे बड़े प्रकार का उपयोग करें" -> long longइसके बजाय क्यों intmax_t?
chux -

आत्मविश्वास चाहिए if (ePtr != str)। इसके अलावा, isspace((unsigned char) *ePtr)नकारात्मक मूल्यों को ठीक से संभालने के लिए उपयोग करें *ePtr
chux -

-3

सी में, आप उपयोग कर सकते हैं int atoi (const char * str),

सी-स्ट्रिंग को अपनी सामग्री की एक अभिन्न संख्या के रूप में व्याख्या करता है, जिसे टाइप इंट के मान के रूप में लौटाया जाता है।


2
जैसा कि मैं atoiप्रश्न में जुड़ा हुआ हूं , मुझे इसकी जानकारी है। प्रश्न स्पष्ट रूप से C के बारे में नहीं है, बल्कि C ++ के बारे में है। -1
यूजीन योकोटा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.