ईओएफ (फाइल के अंत) चरित्र को एक चार प्रकार में संग्रहीत करना


11

मैं डेनिस रिची की द सी प्रोग्रामिंग लैंग्वेज किताब में पढ़ता हूं intजिसका उपयोग ईओएफ को रखने के लिए एक चर के लिए किया जाना चाहिए - इसे पर्याप्त रूप से बड़ा बनाने के लिए ताकि यह ईओएफ मूल्य को पकड़ सके - नहीं char। लेकिन निम्नलिखित कोड ठीक काम करता है:

#include<stdio.h> 

main()  { 
  char c; 
  c=getchar(); 
  while(c!=EOF)  { 
    putchar(c); 
    c=getchar(); 
  } 
} 

जब अधिक इनपुट नहीं होता है, तो getcharEOF लौटाता है। और उपरोक्त कार्यक्रम में, चर c, चर प्रकार के साथ, इसे सफलतापूर्वक आयोजित करने में सक्षम है।

यह काम क्यों करता है? उपर्युक्त पुस्तक में दिए गए स्पष्टीकरण के अनुसार, कोड को काम नहीं करना चाहिए।



5
यदि आप किसी वर्ण को मान के साथ पढ़ते हैं तो यह कोड विफल होने की संभावना है 0xff। उस समस्या का हल getchar()एक परिणाम के रूप में संग्रहीत करना int। आपका प्रश्न अनिवार्य रूप से comp.lang.c FAQ में प्रश्न 12.1 जैसा ही है , जो एक उत्कृष्ट संसाधन है। (इसके अलावा, main()होना चाहिए int main(void), और इसे return 0;बंद करने से पहले जोड़ने के लिए चोट नहीं पहुंचेगी }।)
कीथ थॉम्पसन

1
@ डायलेन: लिंक्ड लेख इस बारे में बिल्कुल सही नहीं है कि यूनिक्स कैसे नियंत्रण-डी का व्यवहार करता है। यह इनपुट स्ट्रीम को बंद नहीं करता है; यह केवल किसी भी भय () का कारण बनता है, जो किसी भी अभी तक-अपठित डेटा के साथ तुरंत वापस लौटने के लिए कंसोल पर रोक रहा है। कई प्रोग्राम ईओएफ को इंगित करने के रूप में फ़्रेड () से शून्य-बाइट रिटर्न की व्याख्या करते हैं, लेकिन फ़ाइल वास्तव में खुली रहेगी और अधिक इनपुट की आपूर्ति करने में सक्षम होगी।
सुपरकैट

जवाबों:


11

आपका कोड काम करने लगता है, क्योंकि अंतर्निहित प्रकार के रूपांतरण गलती से सही काम करने के लिए होते हैं।

getchar()intऐसे मान के साथ रिटर्न करता है जो या तो की सीमा को फिट करता है unsigned charया EOF(जो नकारात्मक होना चाहिए, आमतौर पर यह -1 है)। ध्यान दें कि EOFस्वयं एक चरित्र नहीं है, लेकिन एक संकेत है कि अधिक वर्ण उपलब्ध नहीं हैं।

जब परिणाम को getchar()अंदर से संचित करते cहैं, तो दो संभावनाएँ होती हैं। या तो प्रकार charमूल्य का प्रतिनिधित्व कर सकता है, जिस स्थिति में वह मूल्य है c। या प्रकार मान का प्रतिनिधित्व char नहीं कर सकता है । उस स्थिति में, यह परिभाषित नहीं है कि क्या होगा। इंटेल प्रोसेसर सिर्फ उच्च बिट्स को काटते हैं जो नए प्रकार में फिट नहीं होते हैं (प्रभावी रूप से मूल्य modulo 256 को कम करने के लिए char), लेकिन आपको उस पर भरोसा नहीं करना चाहिए।

अगले चरण के cसाथ तुलना करना है EOF। जैसा EOFकि एक है int, cएक intरूप में अच्छी तरह से परिवर्तित हो जाएगा , में संग्रहीत मूल्य को संरक्षित करना c। यदि cमान को संग्रहीत कर सकता है EOF, तो तुलना सफल होगी, लेकिन यदि मूल्य को संग्रहीत नहीं कियाc जा सकता है , तो तुलना विफल हो जाएगी, क्योंकि टाइप करने के लिए जानकारी का एक अपूरणीय नुकसान हुआ है ।EOFchar

ऐसा लगता है कि आपके संकलक ने charहस्ताक्षरित प्रकार और EOFछोटे के मूल्य को फिट करने के लिए चुना है char। यदि charअहस्ताक्षरित थे (या यदि आपने उपयोग किया था unsigned char), तो आपका परीक्षण विफल हो गया होगा, क्योंकि unsigned charका मान नहीं रखा जा सकता है EOF


यह भी ध्यान दें कि आपके कोड में कोई दूसरी समस्या है। जैसा कि EOFएक चरित्र ही नहीं है, लेकिन आप इसे एक charप्रकार में मजबूर करते हैं , वहाँ एक संभावना है कि वहाँ एक चरित्र है जिसे गलत होने के रूप में समझा जाता है EOFऔर आधे संभावित पात्रों के लिए यह अपरिभाषित है यदि उन्हें सही तरीके से संसाधित किया जाएगा।


charसीमा के बाहर मूल्यों को टाइप करने के लिए जोर लगाना CHAR_MIN.. CHAR_MAXया तो एक कार्यान्वयन-परिभाषित मूल्य प्राप्त करने के लिए आवश्यक है, एक बिट पैटर्न प्राप्त करें जो कार्यान्वयन ट्रैप प्रतिनिधित्व के रूप में परिभाषित करता है, या कार्यान्वयन-परिभाषित सिग्नल बढ़ाता है। ज्यादातर मामलों में, कार्यान्वयन को दो-पूरक कमी के अलावा कुछ भी करने के लिए बहुत सारे अतिरिक्त काम से गुजरना होगा। अगर मानक समिति के लोग इस विचार के लिए सदस्यता लेते हैं कि संकलक को व्यवहार के कार्यान्वयन के लिए प्रोत्साहित किया जाना चाहिए ताकि अन्य कारणों के अभाव में अन्य अधिकांश संकलक के साथ संगत हो सके ...
सुपरकैट

... मैं इस तरह के ज़बरदस्ती को विश्वसनीय मानता हूँ (यह कहने के लिए नहीं कि कोड को अपने इरादों का दस्तावेजीकरण नहीं करना चाहिए, लेकिन यह (signed char)xस्पष्ट और बस के रूप में सुरक्षित माना जाना चाहिए ((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)।) जैसा कि यह है, मुझे कोई संभावना नहीं दिखती है। आज के मानक का अनुपालन करने वाले किसी भी अन्य व्यवहार को लागू करने वाले संकलक; एक खतरा यह होगा कि व्यवहार को "अनुकूलन" के कथित हित में तोड़ने के लिए मानक को बदला जा सकता है।
सुपरकैट

@supercat: मानक ऐसा लिखा जाता है कि किसी भी संकलक को ऐसे कोड का उत्पादन नहीं करना पड़ता जिसमें व्यवहार होता है जो स्वाभाविक रूप से उस प्रोसेसर द्वारा समर्थित नहीं होता है जो इसे लक्षित करता है। अधिकांश अपरिभाषित व्यवहार वहाँ है क्योंकि (मानक लिखने के समय) सभी प्रोसेसर लगातार व्यवहार नहीं करते हैं। कंपाइलर्स के अधिक परिपक्व होने के साथ, कंपाइलर लेखकों ने अधिक आक्रामक अनुकूलन करने के लिए अपरिभाषित व्यवहार का लाभ उठाना शुरू कर दिया है।
बार्ट वैन इनगेन शेनौ

ऐतिहासिक रूप से, स्टैण्डर्ड का इरादा ज्यादातर आपके वर्णन के अनुसार था, हालाँकि स्टैण्डर्ड ने पर्याप्त व्यवहार का वर्णन किया है क्योंकि कुछ सामान्य प्लेटफार्मों के लिए कंपाइलरों की आवश्यकता होती है ताकि कम कोड विनिर्देश के तहत आवश्यकता से अधिक कोड उत्पन्न किया जा सके। इस प्रकार का int i=129; signed char c=i;व्यवहार एक ऐसा व्यवहार है। अपेक्षाकृत कम प्रोसेसरों के पास एक ऐसा निर्देश होता है, जो जब -127 से +127 की सीमा में होता है, तो cबराबर iहोगा और iरेंज -128 में +127 के मानों के अन्य मूल्यों की लगातार संगत मैपिंग करेगा, जो दो-पूरक कमी से भिन्न होता है, या। ..
सुपरकैट

... ऐसे मामलों में लगातार एक संकेत होता है। चूंकि मानक की आवश्यकता है कि कार्यान्वयन या तो एक सुसंगत मानचित्रण का उत्पादन करते हैं या लगातार एक संकेत बढ़ाते हैं, एकमात्र प्लेटफॉर्म जहां मानक दो-पूरक की कमी के अलावा किसी अन्य चीज के लिए जगह छोड़ देगा, संतृप्त-अंकगणित हार्डवेयर के साथ डीएसपी जैसी चीजें होंगी। अनिर्धारित व्यवहार के लिए ऐतिहासिक आधार के रूप में, मैं कहूंगा कि यह मुद्दा सिर्फ हार्डवेयर प्लेटफॉर्म के साथ नहीं है। यहां तक ​​कि एक मंच पर जहां अतिप्रवाह बहुत सुसंगत तरीके से व्यवहार करेगा, यह एक संकलक के जाल के लिए उपयोगी हो सकता है ...
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.