Scanf में उपयोगकर्ता टाइपिंग नल टर्मिनेटर




input (3)

कई प्रणालियों पर, उत्तर "हां" है

आमतौर पर, जादू अनुक्रम नियंत्रण- @ है

@ के लिए वर्ण कोड आम तौर पर 64 है, कम से कम ए (65)। कंट्रोल ए वर्णक कोड 1 है; एक कम वर्ण कोड 0, उर्फ '\0'

नोट करें कि शून्य-लंबाई इनपुट प्राप्त करने के लिए, आपको पहले बाइन-स्पेस वर्ण के रूप में रिक्त बाइट को टाइप करना होगा, और आपको अभी भी इनपुट दर्ज करने के लिए वापसी को हिट करने की आवश्यकता होगी। आपके प्रोग्राम को यह सुनिश्चित करना मुश्किल होगा कि रिक्त बाइट के बाद क्या दर्ज किया गया था।

इनपुट में किसी उपयोगकर्ता का प्रकार नल टर्मिनेटर हो सकता है, जिसके लिए scanf उपयोग किया जाता है, इसलिए इनपुट की लंबाई 0 होगी?

char msg[1000];
scanf("%1000s",msg); // the user would type nothing: '' or '\0'

कुछ सिस्टम टर्मिनल यूजर को Ctrl- @ दबाकर एक NUL बाइट को दर्ज करने की अनुमति देता है scanf() तब इस बाइट को गंतव्य सरणी में संग्रहीत करेगा, परन्तु सबसे अधिक संभावना नहीं है कि इस बाइट को एक शब्द विभाजक का गठन करने की संभावना न हो, इस प्रकार इनपुट पर्सिंग फ़ाइल या एक सफेद स्थान के चरित्र जैसे कि नई लाइन के अंत तक जारी रहेगी।

गंतव्य एरे से कहने का कोई तरीका नहीं है कि यदि अन्य अक्षर के बाद एक NUL बाइट को संग्रहीत किया गया है, और न ही ठीक है कि इस NUL बाइट के बाद कितने आगे वर्ण पढ़े गए हैं। लेकिन अगर scanf() वापस 1 और msg की शून्य लंबाई है, तो एकमात्र संभावना यह है कि प्रयोक्ता ने व्हाइट स्पेस वर्णों के संभवतः खाली अनुक्रम के बाद एक NUL बाइट में प्रवेश किया।

यह केवल एक ही स्ट्रिंग लौटने के लिए fgets() लिए एकमात्र संभावना होगी जब गंतव्य एरे को 1 से बड़े आकार के साथ पारित किया जाएगा।

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

char msg[1000];
if (fgets(msg, sizeof msg, stdin)) {
    int len = strlen(msg);
    if (msg[len - 1] == '\n') {  // potential undefined behavior!
        msg[--len] = '\0'       // potential undefined behavior!
    }
    ...
}

यह भी ध्यान रखें कि आपके कोड में एक दोष है: गंतव्य में स्टोर करने के लिए अधिकतम संख्या 999 , 1000 नहीं होनी चाहिए:

char msg[1000];
if (scanf("%999s",msg) == 1) {
    /* word was read from the user */
    if (*msg == '\0') {
        printf("user entered a NUL byte\n");
    }
}

इनपुट में किसी उपयोगकर्ता का प्रकार नल टर्मिनेटर हो सकता है, जिसके लिए scanf उपयोग किया जाता है, इसलिए इनपुट की लंबाई 0 होगी?

एक नल वर्ण में एक उपयोगकर्ता टाइपिंग के अतिरिक्त, stdin पुनः निर्देशित इनपुट का उपयोग कर सकता है जिसमें शून्य वर्ण शामिल हैं।

foo < data.bin

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

fgets() के समान समस्या है scanf() इस संबंध में: strlen(msg) तरह से वर्णों की संख्या की रिपोर्ट नहीं पढ़ती है।

गैर-मानक getline() अक्षरों की संख्या पढ़ते हैं और इस से बाहर एक तरीका है।

@ स्टार्गेटियर msg में सहेजे गए पात्रों की संख्या को संचित करने के लिए "%n" का उपयोग करने का उल्लेख करता है। शायद पसंद है

char msg[1000 + 1];
int start, end;
if (1 == scanf(" %n%1000s%n", &start, msg, &end)) {
  printf("%d characters read\n", end - start);
}

आईएसी, हम scanf() और परिवार की एक कोने कमजोरियों के साथ सामना करने की कोशिश कर रहे हैं सबसे अच्छा इनपुट इनपुट समाधान अतिरिक्त कारकों पर निर्भर करता है, जो ओपी द्वारा उल्लेखित नहीं है।







scanf