2013-05-06 7 views
8

मैं उद्देश्य-सी के साथ शुरू करने, प्रोग्रामिंग के लिए नया हूं लेकिन आगे बढ़ने से पहले मूल बातें वापस जाने का फैसला किया है। मैं सी पर कुछ समय बिता रहा हूं, और सूचक भ्रम के माध्यम से संघर्ष कर रहा हूं। मेरा सवाल यह है कि कैसे K& आर कहता है कि fgets लागू किया गया है (p165, 2nd ed।) नीचे दी गई कोड मेरी कुछ टिप्पणियों के साथ पाठ से सीधे है।fgets कार्यान्वयन (के एंड आर)

char* fgets(char* s, int n, FILE *iop) 
{ 
    register int c; 
    register char* cs; 
    cs = s; 

    while(--n > 0 && (c = getc(iop)) != EOF) 
    { 
    // put the input char into the current pointer position, then increment it 
    // if a newline entered, break 
    if((*cs++ = c) == '\n') 
     break;   
    } 

    *cs = '\0'; 
    return (c == EOF && cs == s) ? NULL : s; 
} 

1) हम fgets समारोह, जिसका स्थान पर हम उपयोगकर्ता इनपुट स्टोर करने के लिए एक चार * रों गुजरती हैं। स्थानीय char * cs घोषित करने की आवश्यकता क्यों है - और उसके बाद इसे शुरू करें? यदि हम कथन के भीतर सीधे तौर पर हस्तक्षेप/जोड़ नहीं सकते हैं? सीएस के रूप में देखकर एस को इंगित करने के लिए शुरू किया गया है, सीएस को बिल्कुल उसी चीज में जोड़ नहीं रहा है?

2) उपरोक्त के साथ बंधे ... जब फ़ंक्शन वापस आता है, तो यह देखने के लिए एक परीक्षण किया जाता है कि cs == s। यह जरूरी क्यों है?

मुझे लगता है कि मुझे कुछ मौलिक याद आ रही है - मैंने एसओ और Google की जांच की लेकिन इसे काफी समझ नहीं आया। धन्यवाद!

+2

"उद्देश्य-सी के साथ शुरू करना, लेकिन आगे बढ़ने से पहले मूलभूत बातें वापस जाने का फैसला किया है" - उत्कृष्ट, ** प्रत्येक शुरुआत करने वाले को ऐसा करना चाहिए। ** –

+1

मुझे लगता है कि मैं इस तरह का सामना कर रहा था ओब्जे-सी में सी से वापस जाने के बाद से मैं फिर से एक पूर्ण klutz की तरह महसूस करता हूं, लेकिन विभाजन के दोष और अजीब कार्यक्रम व्यवहार के खिलाफ बार-बार अपने सिर को टक्कर मारने के बावजूद, यह निश्चित रूप से प्रयास के लायक है। – drjimmie1976

+0

यह निश्चित रूप से इसके लायक है। उद्देश्य सी को समझने के लिए मास्टरिंग सी अनिवार्य है। –

उत्तर

7

यह अंतिम पंक्ति, cs == s पर चेक की वजह से है। यह तुलना संशोधित सूचक cs मूल s के विरुद्ध यह देखने के लिए जांचती है कि हमने कोई भी चरित्र पढ़ा है या नहीं। अगर हम नहीं तो हम वापस लौटते हैं।

cs का उपयोग करके मूल सूचक s संरक्षित है। यदि s सीधे *cs++ के बजाय *s++ पर छेड़छाड़ की गई थी) तो हमें यह जांचने के लिए एक और तरीका खोजना होगा कि क्या कोई वर्ण पढ़ा गया था या नहीं।

कोई यह भी तर्क दे सकता है कि अकेले फ़ंक्शन पैरामीटर छोड़ना और const के रूप में उनका इलाज करना एक अच्छा अभ्यास है। कुछ प्रोग्रामर कोड स्पष्टता बढ़ाने के तरीके के रूप में इस अभ्यास का पालन करते हैं।

+0

बहुत बहुत धन्यवाद जॉन। इससे इरादा स्पष्ट हो जाता है, लेकिन यदि मैं कर सकता हूं तो कुछ और प्रश्न ... जब 'cs' को 'cs = s' के साथ असाइन किया गया है, तो मुझे लगा कि पॉइंटर्स अब स्मृति के उसी क्षेत्र को इंगित कर रहे थे; इसलिए '* सीएस ++' प्रदर्शन करने से '* s ++' के बराबर होगा। क्या यह धारणा गलत है? – drjimmie1976

+0

क्षमा करें मेरी टिप्पणी का समय समाप्त हो गया है, और मैं भी टिप्पणी मार्कअप गलत कर रहा हूं .... यही कारण है कि मैं अंतिम पंक्ति को समझ नहीं पाया। मैंने सोचा कि दोनों पॉइंटर्स के रूप में देखकर "साझा करना" था, फिर वे समान होंगे जब सी == सीएस अभिव्यक्ति का मूल्यांकन किया गया था। अग्रिम में धन्यवाद। – drjimmie1976

+0

@ GasMan14 वे असाइनमेंट के बाद एक ही पते पर इंगित कर रहे हैं, यह सही है। '* cs ++' हालांकि, 's' को संशोधित नहीं करता है। सुनिश्चित करें कि आप प्राथमिकता को समझते हैं: '* cs ++' '* (cs ++)' not '(* cs) ++' के बराबर है। 'cs ++' increments 'cs', इसे अगले पते पर इंगित करता है, फिर पता *' 'dereferences। 's' नहीं बदला गया है क्योंकि' s' और 'cs' दो अलग-अलग चर हैं। यदि कथन '(* सीएस) ++ 'के बजाय था, तो * * *' s' के मान को बदल देगा। (आपको लगता है कि नहीं, लेकिन '* s'।) –

संबंधित मुद्दे