2011-05-08 18 views
6

मेरे पास दशमलव मूल्यों के प्रारूप में तारों को तोड़ने के लिए दो सहायक कार्य हैं। "23.00", "2.30"स्ट्रोक और सेगमेंटेशन गलती के साथ समस्या

इस पर विचार करें:

char price[4] = "2.20"; 

    unsigned getDollars(char *price) 
    { 
     return atoi(strtok(price, ".")); 
    } 

    unsigned getCents(char *price) 
    { 
     strtok(price, "."); 
     return atoi(strtok(NULL, ".")); 
    } 

अब जब मैं चलाने के नीचे मैं एक विभाजन गलती मिलती है: जब मैं उन्हें अलग से एक निम्नलिखित के बिना चलने

printf("%u\n", getDollars(string)); 
printf("%u\n", getCents(string)); 

हालांकि अन्य, वे ठीक काम करते हैं। मुझे यहां क्या समझ नहीं आ रहा है? क्या मुझे स्ट्रोक की रीसेट करने की ज़रूरत है ??

मेरे समाधान:

strtok मैं इस सवाल का जवाब मैं नीचे चुना है से प्राप्त के बारे में ज्ञान के साथ

, मैं सहायक कार्यों के कार्यान्वयन के इतना है कि वे स्ट्रिंग में पारित प्रतिलिपि पहले बदल गया है, इस प्रकार मूल स्ट्रिंग परिरक्षण और इस समस्या को रोकने:

#define MAX_PRICE_LEN 5 /* Assumes no prices goes over 99.99 */ 

unsigned getDollars(char *price) 
{ 
    /* Copy the string to prevent strtok from changing the original */ 
    char copy[MAX_PRICE_LEN]; 
    char tok[MAX_PRICE_LEN]; 

    /* Create a copy of the original string */ 
    strcpy(copy, price); 

    strcpy(tok, strtok(copy, ".")); 

    /* Return 0 if format was wrong */ 
    if(tok == NULL) return 0; 
    else return atoi(tok); 
} 

unsigned getCents(char *price) 
{ 
    char copy[MAX_PRICE_LEN]; 
    char tok[MAX_PRICE_LEN]; 
    strcpy(copy, price); 

    /* Skip this first part of the price */ 
    strtok(copy, "."); 
    strcpy(tok, strtok(NULL, ".")); 

    /* Return 0 if format was wrong */ 
    if(tok == NULL) return 0; 
    else return atoi(tok); 
} 

उत्तर

5

क्योंकि strtok() इनपुट स्ट्रिंग को संशोधित करता है, तो आप जब यह getCents() समारोह में सीमांकक को खोजने के लिए के बाद आप getDollars() फोन में विफल रहता है समस्याओं में चलाते हैं।

ध्यान दें कि strtok() एक शून्य सूचक देता है जब यह डिलीमीटर खोजने में विफल रहता है। आपका कोड यह जांच नहीं करता है कि strtok() पाया गया कि यह क्या देख रहा था - जो हमेशा जोखिम भरा होता है।


सवाल का आपका अद्यतन दर्शाता है कि आप के बारे में खतरों (बुराइयों?) strtok() के कम से कम कुछ सीखा है। हालांकि, मैं सुझाव दूंगा कि एक बेहतर समाधान केवल strchr() का उपयोग करेगा।

सबसे पहले, हम देख सकते हैं कि atoi() '.' किसी भी प्रकार से परिवर्तित करना बंद कर देगा, तो हम को आसान बनाने getDollars() कर सकते हैं:

unsigned getDollars(const char *price) 
{ 
    return(atoi(price)); 
} 

हम strchr() उपयोग कर सकते हैं - जो स्ट्रिंग संशोधित नहीं करता है - लगता है '.' और फिर इसे बाद पाठ की प्रक्रिया:

unsigned getCents(const char *price) 
{ 
    const char *dot = strchr(price, '.'); 
    return((dot == 0) ? 0 : atoi(dot+1)); 
} 

काफी बहुत आसान है, मुझे लगता।


एक और गोचाचा: मान लीजिए कि स्ट्रिंग 26.6 है; आप बस ऊपर दिए गए संशोधित getCents() की तुलना में कठिन काम करने के लिए है कि 6. इसके अलावा के बजाय 60 वापस जाने के लिए प्राप्त करने के लिए करता है के लिए जा रहे हैं 26.650 दिया, यह 650 वापस आ जाएगी, नहीं 65.

+0

टिप के लिए धन्यवाद, मैंने इसे बोर्ड पर ले लिया है। – Chris

5

यह:

char price[4] = "2.20"; 

price पर नल टर्मिनेटर छोड़ देता है।मुझे लगता है कि आप इस हैं:

char price[5] = "2.20"; 

या बेहतर:

char price[] = "2.20"; 

तो, आप के अंत चलेंगे दूसरी बार आप price से बाहर एक टोकन प्राप्त करने की कोशिश बफ़र। आप बस भाग्यशाली हो रहे हैं कि getCents() हर बार जब आप इसे चलाते हैं तो segfault नहीं करता है।

और आपको strtok का उपयोग करने से पहले लगभग हमेशा एक स्ट्रिंग की एक प्रति बनाना चाहिए (जोनाथन लेफ्लर ने इंगित की समस्या से बचने के लिए)।

+0

मुझे लगता है कि दोनों उत्तर/समस्याएं कारक हैं। मेरा एक ही स्ट्रिंग पर 'strtok()' का उपयोग कर (पुनः) के साथ सामान्य समस्या है। आपका विशेष गैर-स्ट्रिंग वाला एक विशेष मामला है। –

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