स्कैनफ़ प्रारूप स्ट्रिंग

From Vigyanwiki

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

स्कैनएफ शब्द सी स्टैण्डर्ड लाइब्रेरी से आया है, जिसने इस प्रकार के फ़ंक्शन को पॉपुलर बनाया, परन्तु ऐसे फ़ंक्शन C से पहले के होते हैं, और अन्य नामों का उपयोग किया जाता है, जैसे रीडएफ का ALGOL 68 में किया जाता है। स्कैनफ फॉर्मेट स्ट्रिंग्स होता है, जो फॉर्मेटेड इनपुट ( प्रेसिंग ) प्रदान करते हैं, प्रिंटएफ फॉर्मेट स्ट्रिंग के कॉम्प्लीमेंट होते हैं, जो फॉर्मेटेड आउटपुट (टेम्पलेटिंग ) प्रदान करते हैं। ये अधिक सोफिस्टिकेटेड और फ्लेक्सिबल पार्सर या टेम्पलेट इंजन की तुलना में सिंपल फंक्शनलिटी और फिक्स्ड फॉर्मेट प्रदान करते हैं, परन्तु कई पर्पस के लिए सफ्फिसिएंट होते हैं।

इतिहास

माइक लेस्क की पोर्टेबल इनपुट/आउटपुट लाइब्रेरी, स्कैनफ़सहित, ऑफिशियली संस्करण 7 यूनिक्स में यूनिक्स का पार्ट बन गया था।[1]

उपयोग

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

निम्नलिखित सी कोड स्टैण्डर्ड इनपुट स्ट्रीम से अनफॉर्मेट डेसीमल इंटेगेर्स की एक वेरिएबल नंबर को रीड करता है और उनमें से प्रत्येक को भिन्न-भिन्न लाइन में प्रिंट करता है:

#include <stdio.h>

int main(void)
{
    int n;

    while (scanf("%d", &n) == 1)
        printf("%d\n", n);
    return 0;
}

उपरोक्त प्रोग्राम द्वारा प्रोसेस्ड होने के पश्चात्, इंटेगेर्स की एक इर्रेगुलर स्पेस वाली लिस्ट जैसे

456 123 789 456 12
456 1
 2378

कांस्टेंट स्पेस पर इस प्रकार दिखाई देगा:

456
123
789
456
12
456
1
2378

किसी शब्द का प्रिंट आउट लेने के लिए:

#include <stdio.h>

int main(void)
{
    char word[20];

    if (scanf("%19s", word) == 1)
        puts(word);
    return 0;
}

इससे कोई अंतर नहीं पड़ता कि प्रोग्रामर किस डेटा प्रकार को रीड करना चाहता है, आर्गुमेंट (जैसे &n ऊपर) मेमोरी की ओर पॉइंट करने वाला पॉइंटर होना चाहिए। अन्यथा, फ़ंक्शन सही विधि से परफॉर्म नहीं करेगा क्योंकि यह उस वेरिएबल के मेमोरी स्पेस को पॉइंट करने के अतिरिक्त मेमोरी के गलत सेक्शन को ओवरराइट करने का प्रयास करेगा जिसके लिए आप इनपुट प्राप्त करने का प्रयास कर रहे हैं।

अंतिम उदाहरण में एड्रेस-ऑफ ऑपरेटर (&) का उपयोग आर्गुमेंट के लिए नहीं किया जाता है: जैसावर्ड की चूंकि शब्द char एक सारणी डेटा संरचना का नाम है, इस प्रकार यह (सभी कॉन्टेक्स्ट में जिसमें यह किसी एड्रेस का इवैल्यूएट करता है) ऐरे के पहले एलिमेंट के पॉइंटर के समान होता है। जबकि एक्सप्रेशन &word संख्यात्मक रूप से समान वैल्यू पर इवैल्यूएट करेगा, शब्दार्थ की दृष्टि से, इसका एक बिल्कुल अलग अर्थ है कि यह इसके एक एलिमेंट के अतिरिक्त पूरे ऐरे के एड्रेस को प्रदर्शित करता है। स्कैनफ़ स्ट्रिंग्स के लिए आउटपुट असाइन करते समय इस तथ्य को ध्यान में रखा जाना चाहिए ।

चूँकि स्कैनफ़ को मात्र स्टैण्डर्ड इनपुट से रीड करने के लिए स्पेसीफाई किया गया है, इंटरफ़ेस वाली कई प्रोग्रामिंग लैंग्वेजओं, जैसे PHP, एसस्कैनफ़ और एफस्कैनफ़ जैसे डेरिवेटिव होते हैं ,परन्तु स्वयं स्कैनफ़ नही होता है।

फॉर्मेट स्ट्रिंग स्पेसिफिकेशन

स्कैनफ़में फ़ॉर्मेटिंग प्लेसहोल्डर निम् और अधिकप्रिंटएफके समान ही होता हैं, यह एक रिवर्स फ़ंक्शन होता है। प्रिंटएफ की तरह, POSIX एक्सटेंशन n$ को डिफाइन किया गया है।[2]

फॉर्मेट स्ट्रिंग में संभाव्यता ही कभी कांस्टेंट होते हैं (अर्थात, करैक्टर जो प्लेसहोल्डर को फॉर्मेट नहीं कर रहे हैं), मुख्यतः क्योंकि एक प्रोग्राम सामान्यतः ज्ञात डेटा को रीड के लिए डिज़ाइन नहीं किया जाता है, यघपि स्कैनफ़ यदि स्पष्ट रूप से स्पेसीफाई किया गया है तो इन्हें स्वीकार करता है। एक्सेप्शन एक या अधिक व्हाइटस्पेस कैरेक्टर होते है, जो इनपुट में सभी व्हाइटस्पेस कैरेक्टर को हटा देता है।[2]

सबसे अधिक उपयोग किए जाने वाले कुछ प्लेसहोल्डर इस प्रकार हैं:

  • %a : एक फ़्लोटिंग-पॉइंट नंबर को उसके हेक्साडेसिमल नोटेशन में स्कैन करें।
  • %d : एक इन्टिजर को साइंड डेसीमल नंबर के रूप में स्कैन करें।
  • %i : एक इन्टिजर को साइंड नंबर के रूप में स्कैन करें। जो %d के समान होता परन्तु, 0x से पहले आने पर नंबर को हेक्साडेसिमल और 0 से पहले होने पर ऑक्टल के रूप में व्याख्या करता है। उदाहरण के लिए, स्ट्रिंग 031 को %d का उपयोग करके 31 और %i का उपयोग करके 25 में उपयोग करके रीड किया जाएगा। %hi में फ्लैग h में कन्वर्शन और hh एक char में कन्वर्शन को पॉइंट करता है।
  • %u : डेसीमल अनसाइंड इंट के लिए स्कैन करें(ध्यान दें कि C99 स्टैण्डर्ड में इनपुट वैल्यू नेगेटिव साइन वैकल्पिक होते है, इसलिए यदि नेगेटिव साइन रीड जाता है, तो कोई एरर उत्पन्न नहीं होगी और परिणाम एक नेगेटिव नंबर का कॉम्प्लीमेंट होगा, संभवतः यह एक बहुत बड़ा वैल्यू होती है। देखें strtoul() तदनुसार, %hu एक अनसाइंड शोर्ट के लिए स्कैन करता है और %hhu एक अनसाइंड चार के लिए स्कैन करता है।
  • %f : एक फ्लोटिंग पॉइंट नंबर को (फ़िक्स्ड-पॉइंट) नोटेशन में स्कैन करें।
  • %g, %G : किसी फ़्लोटिंग-पॉइंट नंबर को नार्मल या एक्सपोनेंशियल नोटेशन में स्कैन करें। %g लोअर-केस का उपयोग करता है और %G अपर-केस का उपयोग करता है।
  • %x, %X : एक इन्टिजर को असाइंड हेक्साडेसिमल नंबर के रूप में स्कैन करें।
  • %o : एक इन्टिजर को ऑक्टल नंबर के रूप में स्कैन करें।
  • %s : एक करैक्टर स्ट्रिंग को स्कैन करें। स्कैन व्हाइटस्पेस पर टर्मिनेट होता है। स्ट्रिंग के अंत में एक नल करैक्टर स्टोर होता है, जिसका अर्थ है कि आपूर्ति किया गया बफ़र स्पेसीफाई इनपुट लेंग्थ से कम से कम एक करैक्टर लेंग्थ होना चाहिए।
  • %c : एक करैक्टर (चार) को स्कैन करें। कोई जीरो करैक्टर नहीं जोड़ा गया है।
  • व्हाइटस्पेस: कोई भी व्हाइटस्पेस करैक्टर जीरो या अधिक व्हाइटस्पेस करैक्टरों के लिए स्कैन ट्रिगर करता है। रिक्त स्पेस करैक्टरों की नंबर और प्रकार का किसी भी डायरेक्शन में मिलान करने की आवश्यकता नहीं होती है।
  • %lf: डबल फ़्लोटिंग-पॉइंट नंबर रूप में स्कैन करें। "लॉन्ग" स्पेसिफायर के साथ "फ़्लोट" फॉर्मेट।
  • %Lf : एक लॉन्ग डबल फ़्लोटिंग-पॉइंट नंबर के रूप में स्कैन करें। "लॉन्ग लॉन्ग" स्पेसिफायर को "फ़्लोट" करें।
  • %n : कुछ भी अपेक्षित नहीं है। इनपुट से अब तक कंज्यूम किए गए करैक्टरों की नंबर अगले पॉइंटर के माध्यम से स्टोर की जाती है, जो कि इंट का पॉइंटर होना चाहिए। यह कन्वर्शन नहीं है और फ़ंक्शन द्वारा रिटर्न गई नंबर में वृद्धि नहीं करता है।

उपरोक्त का उपयोग नंबर मॉडिफ़ायर औरl , L मॉडिफ़ायर के साथ संयोजन में किया जा सकता है जो परसेंटेज साइन और करैक्टर के मध्य में "लॉन्ग" और "लॉन्ग लॉन्ग" तक स्टैंड रहते हैं। परसेंटेज साइन और उससे पहले के करैक्टरों के मध्य नंबर वैल्यू भी हो सकते हैं, यदि कोई लॉन्ग मॉडिफ़ायर से पहले हो, जो स्कैन किए जाने वाले करैक्टरों की नंबर स्पेसीफाई करता है। एक ऑप्शनल एस्टरिस्क (*) परसेंटेज साइन के ठीक पश्चात् यह प्रदर्शित करता है कि इस फॉर्मेट स्पेसिफायर द्वारा रीड किया गया डेटाम एक करैक्टर में स्टोर नहीं किया जाता है। इस गिराए गए वेरिएबल के लिए फॉर्मेट स्ट्रिंग के पीछे कोई आर्गुमेंट सम्मलित नहीं किया जाना चाहिए।

प्रिंटफ में एफएफ मॉडिफ़ायर स्कैनएफ में उपस्थिति नहीं होती है, जिससे इनपुट और आउटपुट के मोड के मध्य अंतर पैदा होता है। ll और hh मॉडिफ़ायर C90 स्टैण्डर्ड में उपस्थति नहीं होता हैं, परन्तु C99 स्टैण्डर्ड में उपस्थति होता हैं।[3]

फॉर्मेट स्ट्रिंग का एक उदाहरण निम्न प्रकार है

"%7d%s %c%lf"

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

अनेक फ़्लोट प्रकार के करैक्टरों के स्थितियों में a, e, f, g, कई इम्प्लीमेंटेशन अधिकांश को एक ही पार्सर में कोलाप्स करना चयन करते हैं। माइक्रोसॉफ्ट एमएसवीसीआरटी e, f, g इसके साथ करता है,[4] जबकि जीएलआईबीसी चारों के साथ ऐसा करता है।[2]

कमजोरियाँ(वल्नेरेबिलिटीज)

स्कैनफ़ स्ट्रिंग अटैक को फॉर्मेट करने के प्रति संवेदनशील होता है। यह सफिक्स्ड करने के लिए बहुत सावधानी बरतनी चाहिए कि फॉर्मेट स्ट्रिंग अटैक स्ट्रिंग और ऐरे आकार की लिमिटेशन सम्मिलित होती हैं। अधिकांश स्थितियों में यूजर से इनपुट स्ट्रिंग का आकार आरबिटरेरी होता है और इसे पहले निर्धारित नहीं किया जा सकता है स्कैनफ़ फ़ंक्शन एक्सीक्यूट किया गया है। इस का अर्थ है कि %s लेंग्थई स्पेसीफायर्स के बिना प्लेसहोल्डर स्वाभाविक रूप से इनसिक्योर होते हैं और बफ़र ओवरफ़्लो के लिए एक्सप्लॉइट होते हैं। एक अन्य संभावित समस्या डायनामिक फ़ॉर्मेटिंग स्ट्रिंग्स को अनुमति देना है, उदाहरण के लिए कॉन्फ़िगरेशन फ़ाइलों या अन्य यूजर-कंट्रोल्ड फ़ाइलों में स्टोर्ड फ़ॉर्मेटिंग स्ट्रिंग्स। इस स्थिति में स्ट्रिंग आकार की अनुमत इनपुट लेंग्थ तब तक स्पेसीफाई नहीं की जा सकती जब तक कि फ़ॉर्मेटिंग स्ट्रिंग की पहले से जाँच नहीं की जाती और लिमिट्स प्रयुक्त नहीं की जातीं है। इससे संबंधित अतिरिक्त या बेमेल फ़ॉर्मेटिंग प्लेसहोल्डर होता हैं जो वास्तविक वैरार्ग लिस्ट से मैच नही होता हैं। वैरार्ग के विशेष इम्प्लीमेंटेशन के आधार पर, इन प्लेसहोल्डर्स को आंशिक रूप से स्टैक से निकाला जा सकता है या इसमें अनडिजायरेबल या यहां तक ​​कि इनसिक्योर पॉइंटर्स भी हो सकते हैं।

यह भी देखें

संदर्भ

  1. McIlroy, M. D. (1987). A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (Technical report). CSTR. Bell Labs. 139.
  2. 2.0 2.1 2.2 scanf(3) – Linux Programmer's Manual – Library Functions
  3. C99 standard, §7.19.6.2 "The fscanf function" alinea 11.
  4. "स्कैनफ़ प्रकार फ़ील्ड वर्ण". docs.microsoft.com.


बाहरी संबंध