2011-03-02 17 views
6

पॉइंटर को स्टोर करने के लिए स्ट्रिंग के रूप में अनुमति दी गई है जिसके परिणामस्वरूप sscanf पर कॉल किया गया है? मुझे किसी भी दस्तावेज़ीकरण में इसके बारे में कुछ भी नहीं मिला लेकिन ऐसा लगता है कि यह ठीक काम कर रहा है। scanf के साथ वही बात।पूर्ण तर्क sscanf करने की अनुमति दी?

उदाहरण:

int main(int arc, char* argv[]) 
{ 
    char* s = NULL; 
    sscanf("Privjet mir!", "%s", s); 
    printf("s: %s\n", s); 
    return 0; 
} 

आउटपुट: s: (null)

उत्तर

6

नहीं:

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

(http://linux.die.net/man/3/sscanf)

+0

यह उत्तर हमें यह भी सिखाता है कि शून्य को मना करने से स्पष्ट रूप से "शून्य" शब्द का उल्लेख करने की आवश्यकता नहीं है।यह बताते हुए कि "कुछ विशिष्ट प्रकार के डेटा> के लिए सूचक" होना चाहिए, निहित रूप से शून्य को रोकता है। – Lii

1

मैनपेज का कहना है कि, जब %s का उपयोग कर, तर्क स्ट्रिंग और \0 के लिए पर्याप्त जगह के साथ एक सूचक होना चाहिए। तो मेरा अनुमान यह होगा कि आपके मामले में व्यवहार अपरिभाषित है। यह काम कर सकता है, यह स्मृति को भी क्रैश या दूषित कर सकता है और बाद में मुद्दों का कारण बन सकता है।

1

नहीं, इसकी अनुमति नहीं है। sscanf% s एक char * एक बड़े बड़े बफर को इंगित करने की अपेक्षा करता है, printf% s एक नल char * बफर चाहता है। अपरिभाषित व्यवहार में कुछ और परिणाम। (और इसका मतलब है कि कुछ कार्यान्वयन का पता लगाने और एक निश्चित तरीके से एक अशक्त सूचक संभाल, अन्य कार्यान्वयन नहीं हो सकता है हो सकता है)

1

मैं स्पष्ट रूप से NULL और *printf/*scanf के विषय में मानक में कुछ भी नहीं मिला।

मुझे लगता है कि इस अपरिभाषित व्यवहार है, क्योंकि यह एक तर्क है कि फॉर्मेट स्पेसिफायर (§7.19.6.1 ¶13, §7.19.6.2 ¶13) के साथ सुसंगत नहीं है पारित करने के रूप में गिना: %s मतलब है कि एक आप एक वर्ण सरणी के पहले तत्व में एक पॉइंटर पास करने जा रहे हैं (*scanf के लिए अधिग्रहित स्ट्रिंग के लिए काफी बड़ा है, जिसमें NUL-*printf के लिए छिद्रित स्ट्रिंग) - और NULL गुजरने से इस आवश्यकता को पूरा नहीं किया जाता है।


1. इस मामले यूबी के रूप में "मुद्रण (शून्य)" "सिर्फ अधिग्रहण अनदेखी" और पता चलता में, दूसरे प्लेटफार्म पर यह आकाश या सामान्य nasal demons नीचे गिरने विमानों में हो सकता है।

-2

एस को स्मृति आवंटित करें। चरित्र सरणी को एस असाइन करें। फिर कार्यक्रम चलाएं। निम्नलिखित काम करेगा।

int main(int arc, char* argv[]) 
{ 
    char s[100]; 
    sscanf("Privjet mir!", "%[^\t]s", s); 
    printf("s: %s\n", s); 
    return 0; 
} 
+0

वास्तव में मेरे प्रश्न का उत्तर नहीं देता है ... – Lii

4

के रूप में अन्य उत्तर NULL से उल्लेख किया गया है एक अतिरिक्त तर्क के रूप में sscanf को पारित करने के लिए मान्य नहीं है।

http://www.cplusplus.com/reference/cstdio/sscanf अतिरिक्त तर्कों की कहते हैं:

प्रारूप स्ट्रिंग के आधार पर, समारोह अतिरिक्त तर्कों के एक दृश्य की उम्मीद कर सकते हैं, प्रत्येक जहां निकाले पात्रों में से व्याख्या के साथ संग्रहीत किया जाता है आवंटित भंडारण करने के लिए एक सूचक युक्त उचित प्रकार

For the %s specifier these extracted characters are:

गैर-सफ़ेद पात्रों की संख्या कुछ भी पाया पहले खाली स्थान के चरित्र पर रोक। संग्रहीत अनुक्रम के अंत में एक समाप्ति शून्य वर्ण स्वचालित रूप से जोड़ा जाता है।

तो जब "गैर-व्हाइटस्पेस वर्ण" और "निरर्थक शून्य अक्षर" संग्रहीत किया जाता है, तो एक सीगफॉल्ट होगा। कौन वास्तव में क्या दृश्य स्टूडियो निकलेगा (आप परीक्षण कर सकते हैं कि इस http://webcompiler.cloudapp.net/ में विफल रहता है):

enter image description here

अब जहाँ तक गैर दृश्य स्टूडियो compilers, %s विनिर्देशक के लिए libc के निष्कर्षण कोड: https://github.com/ffainelli/uClibc/blob/master/libc/stdio/_scanf.c#L1376 अग्रणी है टिप्पणी: /* We might have to handle the allocation ourselves */ इस वजह से:

GNU सी पुस्तकालय (एक गैरमानक विस्तार के रूप में) गतिशील आवंटन रूपांतरण विनिर्देशक समर्थित a चरित्र के माध्यम से। यह सुविधा कम से कम अब तक glibc 2.0 के रूप में मौजूद प्रतीत होती है।
संस्करण 2.7 के बाद से, glibc a संशोधक के समान उद्देश्य के लिए m संशोधक भी प्रदान करता है।

[Source]

तो क्योंकि एक बफर के लिए libc अर्क sscanf को आंतरिक रूप से निर्माण किया गया और बाद में जाँच करता है कि बफर पैरामीटर कोई निशानी नहीं लगाई यह असाइन करने से पहले, यह कभी नहीं एक NULL बफर पैरामीटर के लिए पात्रों लिखेंगे है।

मैं इतना तनाव नहीं दे सकता कि यह गैर-मानक है, और मामूली लाइब्रेरी अपडेट के बीच भी संरक्षित होने की गारंटी नहीं है। ऐसा करने का एक बेहतर तरीका * उप विनिर्देशक जो उपयोग करने के लिए है:

इंगित करता है डेटा स्ट्रीम से पढ़ लेकिन ध्यान नहीं दिया जा रहा है कि (यानी यह स्थान एक तर्क से बताया में संग्रहीत नहीं है) ।

[Source]

यह उदाहरण के लिए इस तरह पूरा किया जा सकता:

s == NULL ? sscanf("Privjet mir!", "%*s") : sscanf("Privjet mir!", "%s", s); 

जाहिर त्रिगुट का सच शाखा नो-सेशन है, लेकिन मैं इसके साथ शामिल किया है उम्मीद है कि स्ट्रिंग से अन्य डेटा को पढ़ने की उम्मीद है।

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