2010-04-28 13 views
11

मैं निम्नलिखित सी कोड के परिणामों को समझ नहीं पा रहा हूं।सी में atoi() का उपयोग करके मुझे यह अप्रत्याशित परिणाम क्यों मिलता है?

main() 
{ 
    char s[] = "AAA"; 
    advanceString(s); 
} 

void advanceString(p[3]) 
{ 
    int val = atoi(p); 
    printf("The atoi val is %d\n",val); 
} 

यहाँ atoi मान 0 के रूप में दिखाया गया है, लेकिन मैं सही कारण पता नहीं कर सका। मेरी समझ के अनुसार, यह सरणी में प्रत्येक मान के दशमलव समकक्ष का सारांश होना चाहिए? अगर मैं गलत हूं कृपया मुझे सही।

+3

कृपया संकलित वास्तविक कोड पेस्ट करें। –

+2

@ मार्सेलो क्या वास्तव में इस मामले में कोई फर्क पड़ता है? –

+2

शायद, शायद नहीं। लेकिन क्या यह वास्तव में कठिन है, यह देखते हुए कि ओपी ने कार्यक्रम चलाने का नतीजा पहले से ही देखा है? –

उत्तर

12

यह स्ट्रिंग को एक पूर्णांक में बदलने की कोशिश करता है। चूंकि एएए को एक पूर्णांक में परिवर्तित नहीं किया जा सकता है मान 0 है। इसे 42 या कुछ देने का प्रयास करें।

यदि कोई मान्य रूपांतरण निष्पादित नहीं किया जा सकता है, तो शून्य मान वापस कर दिया जाता है।

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

53

atoi() अपने मूल्य में एक पूर्णांक के एक स्ट्रिंग प्रतिनिधित्व धर्मान्तरित देखें। यह मनमाना वर्णों को उनके दशमलव मान में परिवर्तित नहीं करेगा। उदाहरण के लिए:

int main(void) 
{ 
    const char *string="12345"; 

    printf("The value of %s is %d\n", string, atoi(string)); 

    return 0; 
} 

वहाँ मानक सी पुस्तकालय में कुछ भी नहीं है कि 65 या 90 के लिए "Z" में बदल जाएगा 'ए' है, तो आप अपने आप को कि आप के रूप में की उम्मीद कर रहे जो कुछ भी चारसेट के लिए लिखने के लिए, विशेष रूप से आवश्यकता होगी इनपुट।

अब आप जानते हैं कि क्या atoi() करता है, कृपया उसका उपयोग नहीं करते संख्यात्मक इनपुट जो कुछ भी आप के साथ आने से निपटने के लिए। आपको वास्तव में इनपुट के साथ सौदा करना चाहिए जो आप उम्मीद करते हैं। हम्म, जब मैं ए के बजाय 65 दर्ज करता हूं तो क्या होता है? शिक्षकों को चीजों को तोड़ना अच्छा लगता है।

atoi() जो भी कुछ भी जांचने में कोई त्रुटि नहीं करता है, जो कि मनमाने ढंग से इनपुट नाजुक रूप से परिवर्तित करने के लिए कुछ भी निर्भर करता है। इसके बजाय, strtol() (इसे POSIX केंद्रित उदाहरण) का उपयोग करें:

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 

int main(void) 
{ 
    static const char *input ="123abc"; 
    char *garbage = NULL; 
    long value = 0; 

    errno = 0; 

    value = strtol(input, &garbage, 0); 

    switch (errno) { 
     case ERANGE: 
      printf("The data could not be represented.\n"); 
      return 1; 
     // host-specific (GNU/Linux in my case) 
     case EINVAL: 
      printf("Unsupported base/radix.\n"); 
      return 1; 
    } 

    printf("The value is %ld, leftover garbage in the string is %s\n", 
      // Again, host-specific, avoid trying to print NULL. 
      value, garbage == NULL ? "N/A" : garbage); 

    return 0; 
} 

जब रन, इस देता है:

मूल्य 123, में बचे हुए कचरा है स्ट्रिंग एबीसी

है आप तो कचरा बचाने/जांचने की परवाह नहीं है, आप दूसरे तर्क को NULL पर सेट कर सकते हैं। free(garbage) की कोई आवश्यकता नहीं है। यह भी ध्यान दें, यदि आप तीसरे तर्क के रूप में 0 पास करते हैं, तो यह माना जाता है कि इनपुट दशमलव, हेक्स या ऑक्टल प्रतिनिधित्व का वांछित मान है। यदि आपको 10 के रेडिक्स की आवश्यकता है, तो 10 का उपयोग करें - इनपुट विफल होने पर यह विफल हो जाएगा।

आप अधिकतम और न्यूनतम मान के लिए वापसी मान भी देखेंगे long int संभाल सकता है। हालांकि, अगर कोई त्रुटि इंगित करने के लिए लौटा दी जाती है, तो errno सेट है। पाठक के लिए एक अभ्यास 123abc से abc123 में बदलना है।

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

अपने कार्यान्वयन के लिए, सबसे बुनियादी सलाह मैं तुम्हें स्विच की एक श्रृंखला होगी दे सकते हैं, कुछ की तरह:

// signed, since a return value of 0 is acceptable (NULL), -1 
// means failure 
int ascii_to_ascii_val(const char *in) 
{ 
    switch(in) { 
     // 64 other cases before 'A' 
     case 'A': 
      return 65; 
     // keep going from here 
     default: 
      return -1; // failure 

} 

.. तो बस चलने वाले एक पाश में।

या, एक शब्दकोश को पूर्व-पॉप्युलेट करें जो एक लुकअप फ़ंक्शन स्कोप (बेहतर) हो सकता है। आपको हैश की आवश्यकता नहीं होगी, केवल एक कुंजी -> वैल्यू स्टोर क्योंकि आप जानते हैं कि इसमें पहले से क्या होना है, जहां मानक ASCII वर्ण कुंजी हैं, और उनके संबंधित पहचानकर्ता मान हैं।

+1

त्रुटि कोड से मानव पठनीय पाठ प्राप्त करने के लिए आप [strerror] (http://en.wikipedia.org/wiki/Strerror) का उपयोग कर सकते हैं। – Tarantula

+0

जबकि उत्तर सही है, तो अगर उत्तर ओपी को अपनी समस्या को हल करने के बारे में बताएगा तो यह और अधिक मदद करेगा। – Alex

+0

@Alex विश्वास करो या नहीं, मैंने अभी आपकी टिप्पणी देखी है। थोड़ा संपादित किया गया :) –

6

atoi() को एक i (ASCII को पूर्णांक) के रूप में पढ़ें।

atoi() पूर्णांक को दशमलव संख्या का प्रतिनिधित्व करने वाली स्ट्रिंग को परिवर्तित करता है।

char s[] = "42"; 
int num = atoi(s); //The value of num is 42. 
+2

+1 क्योंकि इसमें सबकुछ एक उत्तर की ज़रूरत है ;-) – Frunsi

2

atoi अपने तर्क एक दशमलव (आधार -10) पूर्णांक निरंतर की एक स्ट्रिंग प्रतिनिधित्व हो जाने की उम्मीद; AAA मान्य दशमलव पूर्णांक स्थिर नहीं है, इसलिए atoi 0 देता है क्योंकि यह इंगित करने का कोई अन्य तरीका नहीं है कि इनपुट अमान्य है।

ध्यान दें कि atoi पहले वर्ण में परिवर्तित हो जाएगा जो वैध पूर्णांक निरंतर का हिस्सा नहीं है; दूसरे शब्दों में, "123" और "123w" दोनों को 123 में परिवर्तित कर दिया जाएगा।

अन्य सभी की तरह यह कह रहा है, atoi का उपयोग न करें; इसके बजाय strtol का उपयोग करें।

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