atoi

2011-10-24 7 views
6

का उपयोग करके अलग-अलग परिणाम कोई बता सकता है कि वे कॉल एक ही अपेक्षित परिणाम क्यों नहीं लौट रहे हैं?atoi

unsigned int GetDigit(const string& s, unsigned int pos) 
{ 
     // Works as intended 
     char c = s[pos]; 
     return atoi(&c); 

     // doesn't give expected results 
     return atoi(&s[pos]); 
     return atoi(&static_cast<char>(s[pos])); 
     return atoi(&char(s[pos])); 
} 

टिप्पणी: मैं सबसे अच्छा तरीका है एक int करने के लिए एक char कन्वर्ट करने के लिए नहीं देख रहा हूँ।

+0

यूबी में "इरादे के रूप में काम करता है" एक परिणाम, क्योंकि आप शून्य-समाप्ति वाली स्ट्रिंग के बजाय 'atoi'' एकल 'char' में जा रहे हैं, इसकी उम्मीद है। –

+0

@littleadv: निश्चित रूप से, मेरा मतलब था * सूचक * एक 'char'; और एक सिंगल को पॉइंटर पास करना निश्चित रूप से यूबी है, क्योंकि आपको स्टैक पर इसका अनुसरण करने की कोई गारंटी नहीं है (असल में, यह बिना किसी संदेह के यूबी है क्योंकि आप "एरोई" एक्सेस मेमोरी को "सरणी" के अंतिम तत्व से पहले बना रहे हैं ")। –

+1

@ माटेटेओ: बिना किसी संदेह के, जब तक कि [pos] '0 बाइट नहीं होता है, या अन्यथा एक चरित्र जो 'atoi' को पढ़ने को रोकता है ;-) –

उत्तर

10

आपके प्रयासों में से कोई भी सही नहीं है, जिसमें "इरादे के अनुसार काम करता है" (यह केवल दुर्घटना से काम करने के लिए हुआ) शामिल है। शुरुआत के लिए, atoi() को एक एनयूएल-समाप्त स्ट्रिंग की आवश्यकता होती है, जिसे आप प्रदान नहीं कर रहे हैं।

कैसे निम्नलिखित के बारे में:

unsigned int GetDigit(const string& s, unsigned int pos) 
{ 
     return s[pos] - '0'; 
} 

मतलब यह है कि आप जानते हैं कि s[pos] एक वैध दशमलव अंकों है। यदि आप नहीं करते हैं, तो कुछ त्रुटि जांच क्रम में है।

+0

' atoi' पहले वर्ण में इनपुट स्ट्रिंग को पढ़ना बंद कर देता है कि यह किसी संख्या के हिस्से के रूप में पहचाना नहीं जा सकता है। यह शून्य चरित्र हो सकता है। तो यह वास्तव में लगता है जैसे शून्य चरित्र निश्चित रूप से आवश्यक नहीं है, है ना? लेकिन फिर भी आप सही हैं, मेरे कोई भी समाधान सही नहीं है। –

+0

@RonaldMcBean: समापन चरित्र - जो कुछ भी होता है - स्ट्रिंग का हिस्सा होना चाहिए, क्योंकि स्ट्रिंग के अंत से पहले पढ़ना अपरिभाषित व्यवहार है। – NPE

0

यदि आप सी स्ट्रिंग के रूप में डेटा तक पहुंचना चाहते हैं - s.c_str() का उपयोग करें, और उसके बाद इसे atoi पर पास करें।

atoi एक सी-शैली स्ट्रिंग की अपेक्षा करता है, std::string विभिन्न व्यवहार और विशेषताओं के साथ एक सी ++ वर्ग है। शुरुआत के लिए - इसे पूर्ण समाप्त नहीं किया जाना चाहिए।

0

atoi इसके तर्क के लिए char पर पॉइंटर लेता है। पहली बार प्रयास करें जब आप char c का उपयोग कर रहे हैं तो यह केवल एक वर्ण में पॉइंटर लेता है, इसलिए आपको वह उत्तर मिलता है जो आप चाहते हैं। हालांकि अन्य प्रयासों में आपको char पर पॉइंटर है जो char एस की स्ट्रिंग की शुरुआत हुई है, इसलिए मुझे लगता है कि बाद में प्रयासों में atoi के बाद आप क्या प्राप्त कर रहे हैं, pos पदों में वर्णों से परिवर्तित संख्या है, pos+1, pos+2 और s स्ट्रिंग के अंत तक।

1

चूंकि int atoi(const char* s) वर्णों के क्षेत्र में एक सूचक को स्वीकार करता है, तो आपके पिछले तीन उपयोग & s [pos] से शुरू होने वाले लगातार अंकों के अनुरूप एक संख्या लौटाते हैं, उदा। यह स्थिति 0 से शुरू होने पर "123" जैसी स्ट्रिंग के लिए 123 दे सकता है क्योंकि std::string के अंदर डेटा आवश्यक नहीं है, तो उत्तर कुछ कार्यान्वयन पर कुछ और हो सकता है, यानी अपरिभाषित व्यवहार।

आपका "कामकाजी" दृष्टिकोण अपरिभाषित व्यवहार का भी उपयोग करता है। यह अन्य प्रयासों से अलग है क्योंकि s[pos] के दूसरे स्थान पर मूल्य प्रतिलिपि बनाता है। ऐसा लगता है कि जब तक चरित्र सी के बगल में स्मृति में आसन्न बाइट गलती से शून्य या गैर-अंकीय वर्ण होता है, जिसकी गारंटी नहीं है। तो @aix द्वारा दी गई सलाह का पालन करें।

यह वास्तव में काम करने के लिए आप निम्न कर सकता है: क्या तुम सच में (उस स्थिति में शुरू और समाप्त होने की स्थिति में स्ट्रिंग में बस एक ही चार कनवर्ट करना चाहते हैं के रूप में एक स्ट्रिंग के लिए विरोध किया तो

char c[2] = { s[pos], '\0' }; 
return atoi(c); 
0

स्ट्रिंग के अंत में), आप इसे इन तरीकों से कर सकते हैं:

int GetDigit(const string& s, const size_t& pos) { 
    return atoi(string(1, s[pos]).c_str()); 
} 

int GetDigit2(const string& s, const size_t& pos) { 
    const char n[2] = {s[pos], '\0'}; 
    return atoi(n); 
} 

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

3

क्या आप कर रहे हैं का उपयोग एक std::string, अपने आंतरिक प्रतिनिधित्व से एक चरित्र हो और atoi में इसे करने के लिए एक सूचक फ़ीड है, जो एक const char* कि एक शून्य-समाप्त स्ट्रिंग के लिए अंक की उम्मीद है। std::string अक्षरों को स्टोर करने की गारंटी नहीं है ताकि शून्य समाप्त हो सके, यह केवल भाग्य है कि आपका सी ++ कार्यान्वयन ऐसा प्रतीत होता है।

सही तरीका std::string से s.c_str() का उपयोग करके इसकी सामग्री के शून्य समाप्ति संस्करण के लिए पूछना होगा, फिर atoi पर पॉइंटर का उपयोग करके कॉल करें।

आपका कोड एक और समस्या हैं, तो आपको एक unsigned int करने के लिए atoi का परिणाम कास्ट कर रहे हैं, जबकि atoi रिटर्न एक हस्ताक्षरित intक्या होगा यदि आपकी स्ट्रिंग "-123" है?

+0

+1: दूसरी समस्या और एक अच्छा स्पष्टीकरण इंगित करने के लिए –

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