एक int में एक स्ट्रिंग (चार के रूप में दिया जाता है) को पार्स करने का C ++ तरीका क्या है? मजबूत और स्पष्ट त्रुटि हैंडलिंग एक प्लस (बदले में शून्य ) है।
एक int में एक स्ट्रिंग (चार के रूप में दिया जाता है) को पार्स करने का C ++ तरीका क्या है? मजबूत और स्पष्ट त्रुटि हैंडलिंग एक प्लस (बदले में शून्य ) है।
जवाबों:
नए C ++ 11 में इसके लिए कार्य हैं: stoi, stol, stoll, stoul इत्यादि।
int myNr = std::stoi(myString);
यह रूपांतरण त्रुटि पर एक अपवाद फेंक देगा।
यहां तक कि इन नए कार्यों में अभी भी वही मुद्दा है जो डैन द्वारा नोट किया गया है: वे खुशी से स्ट्रिंग "11x" को पूर्णांक "11" में बदल देंगे।
और देखें: http://en.cppreference.com/w/cpp/string/basic_string/stol
size_t
स्ट्रिंग की लंबाई के बराबर नहीं है, तो यह जल्दी बंद हो गया। यह उस स्थिति में अभी भी 11 लौटेगा, लेकिन pos
स्ट्रिंग की लंबाई के बजाय 2 होगा। coliru.stacked-croched.com/a/cabe25d64d2ffa29
यहां मेरी सलाह का पहला टुकड़ा है: इसके लिए स्ट्रिंगस्ट्रीम का उपयोग न करें । हालांकि पहली बार में यह प्रयोग करने में सरल लग सकता है, आप पाएंगे कि अगर आप मजबूती और अच्छी त्रुटि से निपटना चाहते हैं तो आपको बहुत से अतिरिक्त काम करने होंगे।
यहाँ एक दृष्टिकोण है कि सहज ज्ञान युक्त लगता है जैसे यह काम करना चाहिए:
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
(और परिवार):
किसी अन्य विधि का उपयोग करने का कोई अच्छा कारण नहीं है।
strtol
थ्रेड-सुरक्षित होना चाहिए । POSIX को errno
थ्रेड-लोकल स्टोरेज का भी उपयोग करना पड़ता है। गैर-पॉसिक्स सिस्टम पर भी, errno
मल्टीथ्रेड सिस्टम पर लगभग सभी कार्यान्वयन थ्रेड-लोकल स्टोरेज का उपयोग करते हैं। नवीनतम C ++ मानक को errno
POSIX अनुरूप होना आवश्यक है। नवीनतम सी मानक के errno
लिए थ्रेड-लोकल स्टोरेज की भी आवश्यकता होती है। यहां तक कि विंडोज पर, जो निश्चित रूप से पॉसिक्स कंप्लेंट नहीं है, errno
थ्रेड-सेफ है और, विस्तार से, ऐसा है strtol
।
std::stol
है, जो लगातार स्थिरांक के बजाय अपवादों को फेंक देगा।
std::stol
C ++ भाषा में जोड़े जाने से पहले लिखा था। उस ने कहा, मुझे नहीं लगता कि यह कहना उचित है कि यह "C ++ के भीतर कोडिंग" है। यह कहना मूर्खतापूर्ण है कि std::strtol
सी कोडिंग है जब यह स्पष्ट रूप से सी ++ भाषा का हिस्सा है। मेरा उत्तर पूरी तरह से C ++ पर लागू होता है जब यह लिखा गया था और यह अभी भी नए के साथ लागू होता है std::stol
। अपवादों को फेंकने वाले फ़ंक्शन को कॉल करना हमेशा हर प्रोग्रामिंग स्थिति के लिए सबसे अच्छा नहीं होता है।
यह 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 की टिप्पणी के लिए धन्यवाद)
अच्छा 'पुराना सी रास्ता अभी भी काम करता है। मैं स्ट्रेटोल या स्ट्रैटोल की सलाह देता हूं। रिटर्न की स्थिति और 'एंडप्राट' के बीच, आप अच्छे डायग्नोस्टिक आउटपुट दे सकते हैं। यह भी कई ठिकानों को अच्छी तरह से संभालता है।
आप बूस्ट काlexical_cast
उपयोग कर सकते हैं , जो इसे अधिक सामान्य इंटरफ़ेस में लपेटता है।
असफलता पर lexical_cast<Target>(Source)
फेंकता bad_lexical_cast
है।
आप C ++ मानक लाइब्रेरै से एक स्ट्रिंगस्ट्रीम का उपयोग कर सकते हैं:
stringstream ss(str);
int x;
ss >> x;
if(ss) { // <-- error handling
// use x
} else {
// not a number
}
यदि कोई पूर्णांक पढ़ने की कोशिश कर रहा है, तो एक गैर-अंक का सामना करने पर स्ट्रीम राज्य विफल हो जाएगा।
सी ++ में त्रुटि और धाराओं के नुकसान के लिए स्ट्रीम नुकसान देखें ।
आप स्ट्रिंगस्ट्रीम का उपयोग कर सकते हैं
int str2int (const string &str) {
stringstream ss(str);
int num;
ss >> num;
return num;
}
मुझे लगता है कि ये तीन लिंक इसे जोड़ते हैं:
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;
}
सी ++ स्ट्रिंग टूलकिट लाइब्रेरी (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, या लंबे समय तक।
v = (10 * v) + digit;
के मूल पाठ के साथ स्ट्रिंग इनपुट के साथ अनावश्यक जरूरत से ज्यादा INT_MIN
। तालिका संदिग्ध मूल्य बनाम बस हैdigit >= '0' && digit <= '9'
आप सी ++ 11 है, तो उपयुक्त समाधान आजकल सी ++ में रूपांतरण कार्यों पूर्णांक हैं <string>
: stoi
, stol
, stoul
, stoll
, stoull
। गलत इनपुट दिए जाने पर वे उपयुक्त अपवादों को फेंक देते हैं और strto*
हुड के नीचे तेज और छोटे कार्यों का उपयोग करते हैं ।
यदि आप C ++ के पहले के संशोधन के साथ फंस गए हैं, तो आपके कार्यान्वयन में इन कार्यों की नकल करना आपके लिए आगे-पोर्टेबल होगा।
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;
}
}
एक बोनस के रूप में, यह हेक्साडेसिमल की तरह अन्य ठिकानों को भी संभाल सकता है।
मुझे डैन मोल्डिंग का जवाब पसंद है , मैं इसमें केवल 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 का हिस्सा हो सकता है ...
मैं स्ट्रिंग को इंट में बदलने के तीन तरीके जानता हूं:
या तो 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 ;
}
मुझे डैन का जवाब पसंद है , अपवादों से बचने के कारण जासूसी। एम्बेडेड सिस्टम डेवलपमेंट और अन्य निम्न स्तर सिस्टम डेवलपमेंट के लिए, एक उचित अपवाद फ्रेमवर्क उपलब्ध नहीं हो सकता है।
एक वैध स्ट्रिंग के बाद सफेद-स्थान के लिए एक चेक जोड़ा ... इन तीन पंक्तियों
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;
}
" "
। कोई रूपांतरण नहीं होने strtol()
पर सेट करने के लिए निर्दिष्ट errno
नहीं है। if (s == end) return INCONVERTIBLE;
रूपांतरण न करने के लिए उपयोग करने के लिए बेहतर है । और फिर 2 if (*s == '\0' || *end != '\0')
को सरल कर सकते हैं if (*end)
) || l > LONG_MAX
और || l < LONG_MIN
बिना किसी उद्देश्य के सेवा कर सकते हैं - वे कभी सच नहीं होते हैं।
आप इस परिभाषित विधि का उपयोग कर सकते हैं।
#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 होगा।
atoi
"सी + + रास्ता" की तरह प्रतीत नहीं होता है, स्वीकार किए जाते हैं जैसे अन्य उत्तरों के प्रकाश में std::stoi()
।
मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैं इसके बारे में कई बार और आज तक आया हूं, फिर भी निम्नलिखित विशेषताओं वाले एक अच्छी तरह से टेम्पर्ड समाधान नहीं मिला है:
तो, यहाँ मेरा है, एक परीक्षण पट्टा के साथ। क्योंकि यह हुड के नीचे 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
?
if (ePtr != str)
। इसके अलावा, isspace((unsigned char) *ePtr)
नकारात्मक मूल्यों को ठीक से संभालने के लिए उपयोग करें *ePtr
।
सी में, आप उपयोग कर सकते हैं int atoi (const char * str)
,
सी-स्ट्रिंग को अपनी सामग्री की एक अभिन्न संख्या के रूप में व्याख्या करता है, जिसे टाइप इंट के मान के रूप में लौटाया जाता है।
atoi
प्रश्न में जुड़ा हुआ हूं , मुझे इसकी जानकारी है। प्रश्न स्पष्ट रूप से C के बारे में नहीं है, बल्कि C ++ के बारे में है। -1