सी

2010-12-06 4 views
11

में लूप के दौरान अल्पविराम से अलग अभिव्यक्ति में मैंने कभी भी और कथन पहले कभी नहीं देखा।सी

while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) { 
.. 
.. 
} 

मैंने ऑनलाइन पढ़ा है, जबकि लूप के बाहर आने की स्थिति सही है [! Feof (stdin)]। फिर, क्या ऊपर जबकि बयान के उपयोग के रूप

while(!feof(stdin)) 
{ 
     printf("> "); 
     fgets(str, 100, stdin); 
     ... 
     ... 
} 

इसके अलावा करने के लिए विरोध, जबकि बयान एक अभिव्यक्ति लेता है, 1,1,1 सी में एक वैध अभिव्यक्ति है तो?

उत्तर

17

दिए गए दो लूप का एक ही अर्थ नहीं है। उस तरह से अल्पविराम ऑपरेटर का उपयोग करके, लेखक कोड निर्दिष्ट करने में सक्षम था जिसे प्रत्येक पुनरावृत्ति को निष्पादित किया जाना चाहिए, भले ही लूप स्वयं कभी दर्ज न हो। इसे और अधिक एक do ... while() पाश, या निम्नलिखित की तरह कुछ की तरह है:

printf("> "); 
fgets(str, 100, stdin); 
while(!feof(stdin)) { 
    .. 
    .. 

    printf("> "); 
    fgets(str, 100, stdin); 
} 
4

comma operator एक ऑपरेटर के रूप में अच्छी तरह से सोचा जाता है। बस + एक ऑपरेटर है, इसलिए 2 + 3 एक अभिव्यक्ति है (जो 5 के मान में परिणामस्वरूप होता है), इसलिए , एक ऑपरेटर है, और इस प्रकार 0, 1 एक वैध अभिव्यक्ति है (जिसके परिणामस्वरूप 1 का मान होता है, चूंकि वह अंतिम ऑपरेंड था)।

2

आपका प्रस्तावित संशोधन बराबर नहीं है। यह वह जगह है:

while (1) { 
    printf("> "); 
    fgets(str, 100, stdin); 
    if (feof(stdin)) { break; } 
    ... 
    ... 
} 

मैं बजाय एक समारोह में काम बंद तोड़ने सुझाव है:

int get_input(char* buffer, int size) { 
    printf("> "); 
    fgets(buffer, size, stdin); 
    return !feof(stdin); 
} 

while (get_input(str, 100)) { 
    ... 
    ... 
} 
2

आपका दूसरे उदाहरण पहले की तुलना में अलग व्यवहार है, और एक बग है।

तो कोड की पंक्ति:

fgets(str, 100, stdin); 

में विफल रहता है, क्योंकि यह फ़ाइल के अंत में एक पढ़ा था, तो ब्लॉक के शेष निष्पादित किया जाएगा।

कोड के पहले सेट में, feof() परीक्षण fgets() के बाद होता है जो ईओएफ स्थिति का कारण बनता है, इसलिए while() ब्लॉक निष्पादित नहीं किया जाएगा।

fgets() के बाद रिटर्न शून्य अगर यह EOF को प्रभावित किया है (और बफर में किसी भी डेटा नहीं पढ़ा है), मैं पाश कोड हो सकता है के रूप में:

while (fgets(str, 100, stdin)) { 
    printf("> "); 

    // ... 
} 

जो अभी भी थोड़ा अलग व्यवहार है (नहीं होगा एक कम ">" मुद्रित)। यदि यह महत्वपूर्ण था, तो मैं लूप से पहले printf() का एक अतिरिक्त उदाहरण डालूंगा।

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

+1

वास्तव में, लिखित रूप में पाश पंक्ति की प्रक्रिया के बिना समाप्त होगा 'EOF प्राप्त करने से के बजाय एक नई पंक्ति प्राप्त करने से छोड़ने fgets'। इससे लूप एक अंतिम रेखा को अनदेखा कर देता है जो एक नई लाइन में समाप्त नहीं होता है, जो वांछित व्यवहार हो सकता है, लेकिन अधिक संभावना है कि एक बग। –

+0

@ आर .: मुझे http://www.drpaulcarter.com/cs/common-c-errors.php#4.2 से अवलोकन की याद दिलाई गई है: "लेखक ने अभी तक कोई छात्र feof() फ़ंक्शन का उपयोग नहीं किया है सही ढंग से! " –

1
while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) { 
.. 
.. 
} 

अल्पविराम के अंदर थोड़ी देर के अधिक इस तरह बर्ताव करता है:

int feof_wrapper(FILE * stream) 
{ 
    printf("> "); 
    fgets(str, 100, stream); 
    return feof(stream); 
} 

while(!feof_wrapper(stdin)) { 
.. 
.. 
}