यह गलत है क्योंकि (एक पढ़ने में त्रुटि के अभाव में) यह लेखक की अपेक्षा एक बार लूप में प्रवेश करता है। यदि कोई पठन त्रुटि है, तो लूप कभी समाप्त नहीं होता है।
निम्नलिखित कोड पर विचार करें:
/* WARNING: demonstration of bad coding technique!! */
#include <stdio.h>
#include <stdlib.h>
FILE *Fopen(const char *path, const char *mode);
int main(int argc, char **argv)
{
FILE *in;
unsigned count;
in = argc > 1 ? Fopen(argv[1], "r") : stdin;
count = 0;
/* WARNING: this is a bug */
while( !feof(in) ) { /* This is WRONG! */
fgetc(in);
count++;
}
printf("Number of characters read: %u\n", count);
return EXIT_SUCCESS;
}
FILE * Fopen(const char *path, const char *mode)
{
FILE *f = fopen(path, mode);
if( f == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return f;
}
यह प्रोग्राम लगातार इनपुट स्ट्रीम में वर्णों की संख्या से अधिक प्रिंट करेगा (कोई त्रुटि नहीं पढ़ता है)। उस मामले पर विचार करें जहां इनपुट स्ट्रीम खाली है:
$ ./a.out < /dev/null
Number of characters read: 1
इस मामले में, feof()
किसी भी डेटा को पढ़ने से पहले कहा जाता है, इसलिए यह गलत है। लूप में प्रवेश किया fgetc()
जाता है, (और रिटर्न EOF
) कहा जाता है , और गिनती बढ़ जाती है। फिर feof()
कहा जाता है और सच लौटाता है, जिससे लूप गर्भपात हो जाता है।
ऐसा सभी मामलों में होता है। feof()
तब तक सही नहीं होता जब तक स्ट्रीम पर एक रीड के बाद फाइल का अंत नहीं हो जाता। feof()
यदि अगला रीड फ़ाइल के अंत तक पहुंच जाएगा, तो जांच का उद्देश्य नहीं है। इसका उद्देश्य feof()
रीड एरर और फाइल के अंत तक पहुंचने के बीच अंतर करना है। यदि fread()
रिटर्न 0 है, तो आपको यह निर्धारित करने के लिए feof
/ ferror
का उपयोग करना होगा कि क्या कोई त्रुटि आई थी या यदि सभी डेटा का उपभोग किया गया था। इसी तरह अगर fgetc
रिटर्न EOF
। feof()
के बाद ही उपयोगी है शून्य वापस आ गया है या fgetc
वापस आ गया है EOF
। ऐसा होने से पहले, feof()
हमेशा 0 वापस आ जाएगा।
यह हमेशा आवश्यक पढ़ने की वापसी मान की जाँच करने (या तो एक है fread()
, या एक fscanf()
, या एक fgetc()
) कॉल करने से पहले feof()
।
इससे भी बदतर, उस मामले पर विचार करें जहां एक पढ़ने में त्रुटि होती है। उस स्थिति में, fgetc()
रिटर्न EOF
, feof()
गलत रिटर्न, और लूप कभी समाप्त नहीं होता है। सभी मामलों में, जहां while(!feof(p))
उपयोग किया जाता है, कम से कम लूप के अंदर एक चेक होना चाहिए ferror()
, या बहुत कम से कम जबकि स्थिति के साथ प्रतिस्थापित किया जाना चाहिए while(!feof(p) && !ferror(p))
या एक अनंत लूप की बहुत वास्तविक संभावना है, संभवतः सभी प्रकार के कचरे को उगलते हुए। अमान्य डेटा संसाधित किया जा रहा है।
इसलिए, संक्षेप में, हालांकि मैं यह निश्चितता के साथ नहीं बता सकता कि ऐसी कोई स्थिति नहीं है जिसमें यह लिखना शब्दबद्ध रूप से सही हो सकता है " while(!feof(f))
" (हालांकि एक पढ़ने में त्रुटि पर अनंत लूप से बचने के लिए लूप के अंदर एक और जांच होनी चाहिए) ), यह मामला है कि यह लगभग निश्चित रूप से हमेशा गलत है। और यहां तक कि अगर कोई मामला कभी उत्पन्न हुआ, जहां यह सही होगा, तो यह बहुत ही गलत है कि यह कोड लिखने का सही तरीका नहीं होगा। किसी को भी उस कोड को देखकर तुरंत संकोच करना चाहिए और कहना चाहिए, "यह एक बग है"। और संभवतः लेखक को थप्पड़ मारें (जब तक कि लेखक आपका बॉस न हो, जिसमें विवेक की सलाह दी जाती है।)
feof()
लूप को नियंत्रित करने के लिए उपयोग करना बुरा क्यों है