2014-10-13 2 views
10

मेरी प्रयोगों में इस अभिव्यक्ति`strtod (" 3ex ", और end) का नतीजा क्या है? `Sscanf` के बारे में क्या?

double d = strtod("3ex", &end); 

3.0 साथ d initializes और इनपुट स्ट्रिंग में 'e' चरित्र पर end सूचक देता है। यह वैसे ही है जैसा मैं अपेक्षा करता हूं कि यह व्यवहार करे। 'e' वर्ण एक्सपोनेंट भाग की शुरुआत के रूप में देख सकता है, लेकिन वास्तविक एक्सपोनेंट मान (6.4.4.2 द्वारा आवश्यक) गायब है, इसलिए 'e' को पूरी तरह से स्वतंत्र चरित्र के रूप में माना जाना चाहिए।

हालांकि, जब मैं

double d; 
char c; 
sscanf("3ex", "%lf%c", &d, &c); 

कर मुझे लगता है कि sscanf दोनों '3' और 'e' खपत %lf फॉर्मेट स्पेसिफायर के लिए ध्यान दें। परिवर्तनीय d3.0 मान प्राप्त करता है। परिवर्तनीय c इसमें 'x' के साथ समाप्त होता है। यह दो कारणों से मेरे लिए अजीब लग रहा है।

सबसे पहले, के बाद से भाषा विनिर्देश जब %f फॉर्मेट स्पेसिफायर के व्यवहार का वर्णन strtod को संदर्भित करता है, मैं सहज %lf की उम्मीद है (यानी समाप्ति बिंदु के रूप में एक ही स्थिति चुनें) इनपुट उसी तरह strtod करता है के इलाज के लिए। हालांकि, मुझे पता है कि ऐतिहासिक रूप से scanf इनपुट स्ट्रीम में एक से अधिक वर्ण वापस नहीं लौटा था। यह किसी भी चरित्र से प्रदर्शन कर सकते हैं scanf किसी भी चरित्र द्वारा प्रदर्शन कर सकते हैं। और ऊपर दिए गए उदाहरण में कम-से-कम दो वर्ण दिखने की आवश्यकता है। तो, मान लें कि मैं इस तथ्य को स्वीकार करता हूं कि %lf इनपुट स्ट्रीम से '3' और 'e' दोनों का उपभोग करता है।

लेकिन फिर हम दूसरे अंक में भाग लेते हैं। अब sscanf को को double टाइप करने के लिए परिवर्तित करना होगा। "3e" फ़्लोटिंग-पॉइंट निरंतर का एक वैध प्रतिनिधित्व नहीं है (फिर, 6.4.4.2 के अनुसार एक्सपोनेंट मान वैकल्पिक नहीं है)। मैं इस इनपुट को ग़लत मानने के लिए sscanf की अपेक्षा करता हूं: %lf रूपांतरण के दौरान समाप्त करें, 0 पर वापस जाएं और d और c अपरिवर्तित छोड़ दें। हालांकि, उपर्युक्त sscanf सफलतापूर्वक पूर्ण हो गया है (2 लौटा रहा है)।

यह व्यवहार मानक पुस्तकालय के जीसीसी और एमएसवीसी कार्यान्वयन के बीच संगत है। उपभोक्ता से अधिक strtod करता है और सफलतापूर्वक "3e" के रूप में इस तरह के दृश्यों को परिवर्तित:

तो, मेरे सवाल का, सी भाषा में कहां मानक दस्तावेज़ यह जैसा कि ऊपर वर्णित दो अंक ऊपर की चर्चा करते हुए sscanf व्यवहार करने के लिए अनुमति नहीं है है?

मेरे प्रयोग परिणामों को देखकर मैं शायद sscanf के व्यवहार को "रिवर्स इंजीनियर" कर सकता हूं: जितना अधिक "सही दिखता है" उपभोग नहीं करता है और फिर उपभोगित अनुक्रम को strtod पर ले जाता है। इस तरह 'e'%lf द्वारा उपभोग किया जाता है और फिर strtod द्वारा अनदेखा किया जाता है। लेकिन भाषा विनिर्देश में बिल्कुल ठीक था?

+0

शायद इस कारण में तथ्य (हालांकि बहुत अच्छा बहाना नहीं है) इस तथ्य में निहित है कि 'sscanf' 'stdio' में है और' strtod'' stdlib' में है। –

+0

वास्तव में मुझे यकीन नहीं है कि मैं समझता हूं: एसएसकेएनएफ का नतीजा आपके लिए अजीब क्यों लगता है? आपने वास्तव में क्या उम्मीद की थी? क्या आप थोड़ा और विवरण दे सकते हैं? – HighPredator

+2

@ हाइप्रेडेटर: ओपी का अर्थ है कि परिवर्तनीय 'सी' मान को '' ई 'प्राप्त करना चाहिए और मान' x'' नहीं होना चाहिए। या शायद इसे किसी भी मूल्य को प्राप्त नहीं करना चाहिए, और कार्य 'sscanf' को 2 के बजाय 1 वापस करना चाहिए (इसलिए यह सटीक रूप से' strtod' के व्यवहार को अनुकरण करता है)। –

उत्तर

1

मैं सिर्फ die.net

पर नीचे दिए गए विवरण strtof(), और strtold() फ़ंक्शन स्ट्रिंग की प्रारंभिक भाग दोगुना करने के लिए nptr, नाव द्वारा की ओर इशारा किया कनवर्ट करते हैं, और पाते हैं strtod(), क्रमशः डबल प्रतिनिधित्व।

स्ट्रिंग (के प्रारंभिक भाग) की उम्मीद प्रपत्र वैकल्पिक सफेद स्थान प्रमुख है के रूप में isspace (3), एक वैकल्पिक प्लस ('+') या ऋण चिह्न ('-') द्वारा मान्यता प्राप्त या तो और फिर (i) दशमलव संख्या, या (ii) हेक्साडेसिमल संख्या, या (iii) एक अनंतता, या (iv) एक नैन (संख्या-संख्या नहीं)।

एक दशमलव संख्या दशमलव अंक संभवतः एक मूलांक चरित्र (दशमलव बिंदु, स्थान पर निर्भर है, आमतौर पर '।') से युक्त है, वैकल्पिक रूप से एक दशमलव प्रतिपादक के बाद की एक अरिक्त अनुक्रम के होते हैं। एक दशमलव प्रतिपादक एक 'ई' या 'ई', एक वैकल्पिक प्लस या ऋण चिह्न के बाद, दशमलव अंकों के एक अरिक्त अनुक्रम के बाद के होते हैं, और 10

एक हेक्साडेसिमल संख्या की एक शक्ति से गुणा इंगित करता है इसमें "0x" या "0X" होता है जिसके बाद हेक्साडेसिमल अंकों के एक nonempty अनुक्रम होते हैं, संभवतः एक रेडिक्स वर्ण, वैकल्पिक रूप से बाइनरी एक्सपोनेंट के बाद होता है। एक बाइनरी एक्सपोनेंट में 'पी' या 'पी' के होते हैं, उसके बाद वैकल्पिक प्लस या माइनस साइन के बाद दशमलव अंकों के एक nonempty अनुक्रम द्वारा पीछा किया जाता है, और गुणा 2 की शक्ति से गुणा करता है। कम से कम एक radix चरित्र और बाइनरी एक्सपोनेंट उपस्थित होना चाहिए।

एक अनन्तता या तो "आईएनएफ" या "इन्फिनिटी" है, मामले को अनदेखा कर रहा है।

एक एनएएन वैकल्पिक रूप से '(', वर्णों का अनुक्रम 'के बाद "नैन" (अनदेखा मामला) है, इसके बाद') '। चरित्र स्ट्रिंग एक कार्यान्वयन-निर्भर तरीके से एनएएन के प्रकार में निर्दिष्ट करता है।

तो मैं एक प्रयोग किया जाता मैं नीचे जीसीसी के साथ

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

char head[1024], *tail; 

void core(const char *stmt){ 
    sprintf(head, "%s", stmt); 
    double d=strtod(head, &tail); 
    printf("cover %s to %.2f with length=%ld.\n", head, d, tail-head); 
} 

int main(){ 
    core("3.0x"); 
    core("3e"); 
    core("3ex"); 
    core("3e0x"); 

    return 0; 
} 

कोड निष्पादित, और परिणाम

cover 3.0x to 3.00 with length=3. 
cover 3e to 3.00 with length=1. 
cover 3ex to 3.00 with length=1. 
cover 3e0x to 3.00 with length=3. 

तो मिलता है, ऐसा लगता है कि वहाँ के पीछे 'ई कुछ अंकों का होना चाहिए '।

sscanf के लिए, मैं जीसीसी कोड के साथ एक और प्रयोग का प्रदर्शन:

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

char head[1024]; 

void core(const char *stmt){ 
    int i;sscanf(stmt, "%x%s", &i, head); 
    printf("sscanf %s catch %d with '%s'.\n", stmt, i, head); 
} 

int main(){ 
    core("0"); 
    core("0x0g"); 
    core("0x1g"); 
    core("0xg"); 

    return 0; 
} 

तो नीचे दिए गए आउटपुट मिलता है:

sscanf 0 catch 0 with ''. 
sscanf 0x0g catch 0 with 'g'. 
sscanf 0x1g catch 1 with 'g'. 
sscanf 0xg catch 0 with 'g'. 

ऐसा लगता है कि sscanf और वर्ण को पकड़ने की कोशिश और अगर वापस नहीं किया जा देंगे यह जुड़ा हुआ है कि यह कानूनी रूप से कानूनी है (समेकित स्थिति के साथ अवैध हो सकता है)।

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