2008-09-16 13 views
8

केवल एएनएसआई सी का उपयोग करके, उचित निश्चितता के साथ सबसे अच्छा तरीका क्या है, यह निर्धारित करें कि सी शैली स्ट्रिंग या तो एक पूर्णांक या वास्तविक संख्या है (यानी फ्लोट/डबल)?यह निर्धारित करें कि कोई स्ट्रिंग एक पूर्णांक है या एएनएसआई सी

उत्तर

34

एटोई और एटॉफ़ का उपयोग न करें क्योंकि इन कार्यों में विफलता पर 0 वापस आते हैं। पिछली बार मैंने चेक किया 0 एक वैध पूर्णांक और फ्लोट है, इसलिए प्रकार निर्धारित करने के लिए कोई उपयोग नहीं है।

स्ट्रेटो {एल, उल, ull, ll, d} फ़ंक्शंस का उपयोग करें, क्योंकि इन सेट विफलता पर गलत है, और यह भी रिपोर्ट करता है कि परिवर्तित डेटा कहां समाप्त हुआ।

strtoul: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

इस उदाहरण मानता है कि स्ट्रिंग एकल मान परिवर्तित किया होता है।

#include <errno.h> 

char* to_convert = "some string"; 
char* p = to_convert; 
errno = 0; 
unsigned long val = strtoul(to_convert, &p, 10); 
if (errno != 0) 
    // conversion failed (EINVAL, ERANGE) 
if (to_convert == p) 
    // conversion failed (no characters consumed) 
if (*p != 0) 
    // conversion failed (trailing data) 

उनका कहना है कि मैं पहली बार 0 पर errno स्थापित करने के लिए भूल गया के लिए जोनाथन Leffler के लिए धन्यवाद।

+0

क्षमा करें, मुझे पता था कि यह काफी पुराना है, लेकिन इस पंक्ति में, हमारे पास कोई त्रुटि नहीं है? हस्ताक्षरित लंबी वैल = strtoul (to_convert, और पी, 10); सही अहस्ताक्षरित लंबे errno = strtoul (to_convert, और पी, 10) होगा है; – vodkhang

+0

@ वोदखांग यह मान्य कोड है, लेकिन आपको अपने कंपाइलर के आधार पर #in3e का उपयोग करना पड़ सकता है। errno अनिवार्य रूप से एक वैश्विक चर है कि एक त्रुटि कोड के साथ सेट किया जा सकता है। इसे एक मैक्रो या "संशोधित अंतराल" के रूप में लागू किया जा सकता है। –

+0

'errno' ** ** एक मैक्रो है जो एक संशोधित अंतराल तक फैलता है। आम तौर पर यह '(* __ errno_location())' या इसी तरह का विस्तार करता है। किसी भी सिरदर्द को बचाने के लिए –

2

मुझे लगता है कि आप स्ट्रिंग के माध्यम से कदम उठा सकते हैं और जांच सकते हैं कि इसमें . वर्ण हैं या नहीं। यह केवल पहली बात है जो मेरे सिर में चली गई, इसलिए मुझे यकीन है कि अधिक निश्चित होने के अन्य (बेहतर) तरीके हैं।

+0

और 'है जोड़ने को देखने के लिए कर सकता है, 'चरित्र। स्थानीयकरण के बारे में मत भूलना। – Arafangion

3

atoi और atof परिवर्तित हो जाएगा या 0 अगर यह नहीं कर सकता है।

+0

यह 0 के लिए काम नहीं करता है ... – Patrick

+0

निश्चित - आपका उत्तर निश्चित रूप से उस मामले को शामिल करता है। – itsmatt

+0

मैंने इस भ्रम को रोकने के लिए अपना प्रदर्शन नाम बदल दिया है! –

1

यह वास्तव में इस बात पर निर्भर करता है कि आप पहली जगह क्यों पूछ रहे हैं।

यदि आप सिर्फ एक संख्या का विश्लेषण करना चाहते हैं और यह नहीं जानते कि यह एक फ्लोट या पूर्णांक है, तो बस एक फ्लोट पार्स करें, यह सही ढंग से एक पूर्णांक को भी सही ढंग से पार्स करेगा।

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

1

एटोई और एटॉफ संख्या को रूपांतरित कर देगा, भले ही गैर संख्यात्मक वर्ण पीछे हो। हालांकि, यदि आप स्ट्रेटोल और स्ट्रेटोड का उपयोग करते हैं तो यह न केवल प्रमुख सफेद स्थान और वैकल्पिक संकेत छोड़ देगा, बल्कि आपको पहले वर्ण में पॉइंटर के साथ नंबर में नहीं छोड़ेगा। फिर आप जांच सकते हैं कि बाकी सफेद जगह है।

9

sscanf का उपयोग करना, आप कुछ हो सकता है यदि स्ट्रिंग एक नाव है या int या जो कुछ भी विशेष मामला 0 करने के लिए, के रूप में atoi साथ और समाधान atof मामला है बिना।

int i; 
float f; 
if(sscanf(str, "%d", &i) != 0) //It's an int. 
    ... 
if(sscanf(str "%f", &f) != 0) //It's a float. 
    ... 
+1

मुझे पूरा यकीन है कि आपको एसएसकेएनएफ के रिटर्न वैल्यू का परीक्षण करने की ज़रूरत है ताकि यह सुनिश्चित किया जा सके कि पूरी स्ट्रिंग को परिवर्तित किया गया हो, अन्यथा "% d" असफल नहीं होगा अगर यह "1.374" है, तो यह 1 लौटाएगा। –

+0

सच है। इसे पहले% f के परीक्षण के द्वारा भी हल किया जा सकता है, लेकिन इससे "1." के साथ समस्याएं उत्पन्न होती हैं। निजी तौर पर, मुझे आपके समाधान को प्रस्तुत करने वालों में से सबसे अच्छा पसंद है। – Patrick

+0

@Patrick_O स्ट्रिंग लम्बाई के विरुद्ध 'sscanf' की वापसी की जांच करना काम नहीं करेगा, क्योंकि यह सफलतापूर्वक परिवर्तित वस्तुओं की संख्या देता है, रूपांतरण के लिए उपयोग किए गए वर्णों की संख्या नहीं। लेकिन '% n' प्रारूप यहां मदद कर सकता है। – Jens

2

उपयोग strtol/strtoll (नहीं atoi) पूर्णांकों की जाँच करने के:

यहाँ कुछ उदाहरण कोड है। युगल जांचने के लिए स्ट्रॉफ/स्ट्रेट (एटीओफ़) का उपयोग करें।

atoi और atof स्ट्रिंग के प्रारंभिक भाग को परिवर्तित करते हैं, लेकिन आपको यह नहीं बताते कि वे सभी स्ट्रिंग का उपयोग करते हैं या नहीं। strtol/strtod आपको बताता है कि वर्ण परिवर्तित होने के बाद अतिरिक्त जंक था या नहीं।

इसलिए दोनों मामलों में, एक गैर-शून्य टेल पैरामीटर में पास करना याद रखें, और जांचें कि यह स्ट्रिंग के अंत तक इंगित करता है (यानी, ** टेल == 0)। अंडरफ्लो और ओवरफ़्लो के लिए वापसी मान भी देखें (विवरण के लिए मैन पेज या एएनएसआई मानक देखें)।

ध्यान दें कि स्ट्रॉड/स्ट्रेटोल प्रारंभिक व्हाइटस्पेस छोड़ देता है, इसलिए यदि आप प्रारंभिक व्हाइटस्पेस के साथ तारों को बीमार प्रारूप के रूप में देखना चाहते हैं, तो आपको पहले अक्षर की जांच करने की भी आवश्यकता है।

3

मैं पैट्रिक_ओ से सहमत हूं कि स्ट्रेटो {एल, उल, ull, ll, d} फ़ंक्शंस जाने का सबसे अच्छा तरीका है। यद्यपि देखने के लिए कुछ बिंदु हैं।

  1. कार्यों को कॉल करने से पहले शून्य पर त्रुटि सेट करें; आपके लिए कोई फ़ंक्शन नहीं करता है।
  2. ओपन समूह पृष्ठ से लिंक (जो मैं देख कि पैट्रिक यह भी जोड़ा था से पहले के लिए गया था) बताते हैं errno सेट नहीं किया जा सकता है। यदि मूल्य सीमा से बाहर है तो यह ERANGE पर सेट है; यह सेट हो सकता है (लेकिन समान रूप से, सेट नहीं किया जा सकता है) यदि तर्क अमान्य है तो EINVAL पर।

हाथ में काम के आधार पर, मैं कभी कभी रूपांतरण सूचक के अंत से लौटाए गए सफेद स्थान अनुगामी छोड़ करने की व्यवस्था करेंगे और फिर शिकायत (अस्वीकार) यदि अंतिम वर्ण समाप्त रिक्त नहीं है '\ 0 '। या मैं मैला हो सकता हूं और अंत में कचरा दिखाई दे सकता हूं, या मैं वैकल्पिक गुणक जैसे 'के', 'एम', 'जी', 'टी' को किलोबाइट्स, मेगाबाइट्स, गीगाबाइट्स, टेराबाइट्स, या किसी अन्य के लिए स्वीकार कर सकता हूं संदर्भ के आधार पर आवश्यकता।

+0

मैंने एक errno = 0 जोड़ा है; मेरे कोड उदाहरण के लिए, धन्यवाद। –

0

ठीक है, अगर तुम strtoul की तरह एक नया कार्य का उपयोग कर की तरह महसूस नहीं करते हैं, तो आप सिर्फ एक और strcmp बयान करता है, तो स्ट्रिंग 0.

यानी

if(atof(token) != NULL || strcmp(token, "0") == 0) 
+0

यह सोचता है कि "0.0" (और इसके अन्य बदलाव) संख्याएं नहीं हैं। – Michael