2011-03-03 9 views
9

मुझे लंबाई के बारे में धारणा किए बिना पाठ की एक पंक्ति (एक नई लाइन द्वारा समाप्त) पढ़ने की जरूरत है। इसलिए मैं अब संभावनाओं को सामना करना पड़ता है:सी fgets बनाम fgetc पढ़ने के लिए

  • उपयोग fgets और हर बार की जाँच करता है, तो अंतिम वर्ण कोई नई पंक्ति है और लगातार एक बफर
  • को संलग्न fgetc और कभी-कभी realloc बफर
का उपयोग कर प्रत्येक चरित्र पढ़ें

अंतर्ज्ञान मुझे fgetc संस्करण धीमा हो सकता है, लेकिन फिर मैं नहीं देखता कि fgets प्रत्येक चरित्र की जांच किए बिना इसे कैसे कर सकता है (मेरा अंतर्ज्ञान हमेशा अच्छा नहीं होता है)। रेखाएं काफी बड़ी हैं इसलिए प्रदर्शन महत्वपूर्ण है।

मैं प्रत्येक दृष्टिकोण के पेशेवरों और विपक्ष को जानना चाहता हूं। पहले ही, आपका बहुत धन्यवाद।

उत्तर

1

मैं fgets() का उपयोग गतिशील स्मृति आवंटन के साथ करने का सुझाव देता हूं - या आप getline() पर इंटरफ़ेस की जांच कर सकते हैं जो POSIX 2008 मानक में है और हाल ही में लिनक्स मशीनों पर उपलब्ध है। यह आपके लिए स्मृति आवंटन सामग्री करता है। आपको बफर की लंबाई के साथ-साथ इसके पते पर टैब रखना होगा - ताकि आप जानकारी को संभालने के लिए खुद को एक संरचना भी बना सकें।

हालांकि fgetc() भी काम करता है, यह मामूली रूप से खराब है - लेकिन केवल मामूली रूप से। कवर के नीचे, यह fgets() के समान तंत्र का उपयोग करता है। आंतरिक गतिशील ऑपरेशन का फायदा उठाने में सक्षम हो सकते हैं - strchr() के समान - जो तब उपलब्ध नहीं हैं जब आप सीधे fgetc() पर कॉल करते हैं।

+0

'fgets' के साथ' गेटलाइन 'फ़ंक्शन को कार्यान्वित करते समय एक सीमा यह है कि एक ही समय में एक न्यूलाइन वर्ण के साथ समाप्त नहीं होने वाली नल बाइट्स ** और ** फ़ाइलों को संभालना असंभव है। यदि 'fgets' एक ईओएफ स्थिति का सामना करता है और बिना किसी न्यूलाइन चरित्र के लौटाता है, तो आप केवल यह मान सकते हैं कि स्ट्रिंग पहले नल बाइट पर समाप्त होती है। (अन्य मामलों में, आप यह जानने के लिए 'strchr (buf,' \ n ')' कर सकते हैं कि रीडिंग रोका गया है या यदि कोई '\ n'' नहीं है, तो आपको' realloc' 'की आवश्यकता है।) – mk12

+0

यदि फ़ाइल में शून्य बाइट्स हैं, यह एक टेक्स्ट फ़ाइल नहीं है। (यह एक विस्तृत चरित्र फ़ाइल हो सकती है, लेकिन फिर आपको इसे पढ़ने के लिए विस्तृत वर्ण I/O फ़ंक्शंस का उपयोग करने की आवश्यकता है।) और 'fgets()' को उन फ़ाइलों को संभालने के लिए डिज़ाइन नहीं किया गया है जिनमें शून्य बाइट्स हैं - ठीक है क्योंकि यह कोई नहीं देता है विश्वसनीय संकेत यह कितने बाइट्स पढ़ता है। यदि आपकी डेटा फ़ाइल में शून्य बाइट्स हैं, तो आपको इसे पढ़ने के लिए 'fgets() 'का उपयोग नहीं करना चाहिए। –

+0

http://linux.die.net/man/3/getline (रिटर्न वैल्यू सेक्शन) ऐसा लगता है कि यह एक उपयोगी बात हो सकती है। यही वह जगह है जहां मुझे विचार आया, हालांकि मुझे लगता है कि मैं आपसे सहमत हूं। अब जब मैं इसके बारे में सोचता हूं, शायद यह केवल वहां उल्लेख किया गया है क्योंकि यह '\ n'' के अलावा एक डिलीमीटर का उपयोग करते समय उपयोगी हो सकता है। – mk12

0

यदि आप अधिकतम लाइन लंबाई भी सेट कर सकते हैं, तो एक बड़ा भी, तो एक fgets चाल करेगा। यदि नहीं, तो एकाधिक fgets कॉल अभी भी एकाधिक fgetc कॉल से तेज होंगे क्योंकि बाद वाले का ओवरहेड अधिक होगा।

एक बेहतर जवाब यह है कि प्रदर्शन अंतर के बारे में चिंता करने योग्य नहीं है जब तक कि आपको यह नहीं करना चाहिए। यदि fgetc पर्याप्त तेज़ है, तो इससे कोई फर्क नहीं पड़ता?

+0

यह भी ध्यान दें कि 'getc' आमतौर पर मैक्रो के रूप में लागू होता है और इसलिए' fgetc' से तेज़ होता है, और जब तक आप सावधान रहें तब तक उपयोग किया जाना चाहिए (तर्क अभिव्यक्ति नहीं हो सकता है)। – mk12

2

क्या आपका पर्यावरण getline(3) फ़ंक्शन प्रदान करता है? यदि हां, तो मैं कहूंगा कि इसके लिए जाओ।

मुझे लगता है कि बड़ा लाभ यह है कि यह बफर को आवंटित करता है (यदि आप चाहते हैं), और realloc() बफर जो आप पास करते हैं तो बहुत छोटा है। (तो इसका मतलब है कि आपको malloc() से प्राप्त कुछ में पास करने की आवश्यकता है)।

यह fgets/fgetc के कुछ दर्द से छुटकारा पाता है, और आप उम्मीद कर सकते हैं कि जिसने सी पुस्तकालय लिखा है, उसे लागू करने से यह कुशल बनने का ख्याल रखता है।

बोनस: लिनक्स पर मैन पेज का एक अच्छा उदाहरण है कि इसे कुशल तरीके से कैसे उपयोग किया जाए।

+0

दुर्भाग्यवश (मुझे खेद है कि मैंने इस सवाल का जिक्र नहीं किया है) मुझे मानक सामग्री का उपयोग करने की आवश्यकता है :-(गेटलाइन फ़ंक्शंस निश्चित रूप से आकर्षक लगता है। – nc3b

+1

अच्छा, यह मानक है (मानक की कुछ परिभाषा के लिए)। देखें [ओपन ग्रुप बेस निर्दिष्टीकरण अंक 7] (http://pubs.opengroup.org/onlinepubs/9699919799/), उर्फ ​​"आईईईई स्टडी 1003.1 ™ -2008" उर्फ ​​"पॉज़िक्स सी 2008"। लेकिन मानक! = व्यापक रूप से, दुर्भाग्य से। मुझे तुम्हारा दर्द महसूस होता है गेटलाइन सेक्सी है :-) – Mat

+0

'getline()' कार्यक्षमता अच्छी है; नाम 'getline() 'उपयोगकर्ता नामस्थान पर एक अत्याचारी घुसपैठ है, विविध इंटरफेस की विस्तृत श्रृंखला के साथ अधिक व्यापक रूप से उपयोग किए जाने वाले फ़ंक्शन नामों में से एक को पूर्व-खाली करना (उदाहरण के लिए, के एंड आर 1 और 2 देखें)। यह उस नाम का उपयोग करने का एक * अपमानजनक * निर्णय था; यह कार्यक्षमता प्रदान करने के लिए एक * उत्कृष्ट * निर्णय था। सीआरएलएफ लाइन के अंतराल को संभालने की क्षमता का एकमात्र आश्चर्यजनक बात यह है कि; संबंधित 'getdelim()' फ़ंक्शन सीआर या एलएफ या एनयूएल लाइन एंडिंग को संभाल सकता है, लेकिन सीआरएलएफ लाइन एंडिंग को संभाल नहीं सकता है। –

0

मैं एक बड़ा बफर आवंटित करता हूं और फिर यदि आप लाइन के अंत तक नहीं पढ़ते हैं तो fgets, checking, reallocing और repeating का उपयोग करें।

प्रत्येक बार जब आप पढ़ते हैं (या तो fgetc या fgets के माध्यम से) आप एक सिस्टम कॉल कर रहे हैं जिसमें समय लगता है, तो आप कितनी बार घटित होते हैं, कम करना चाहते हैं, इसलिए कम समय में fgets को कॉल करना और स्मृति में पुनरावृत्ति करना तेज है।

यदि आप फ़ाइल से पढ़ रहे हैं, तो फ़ाइल में mmap() आईएनजी एक और विकल्प है।

+0

मुझे सिस्टम कॉल भाग पर आपको विरोधाभास करना है: stdio लाइब्रेरी बफरिंग करता है इसलिए मुझे नहीं लगता कि प्रत्येक फ़ंक्शन कॉल का सिस्टम कॉल में अनुवाद किया जाएगा। मैं गलत हो सकता है – nc3b

+0

यह सच है, लेकिन fgets के साथ वह बेहतर अनाज नियंत्रण होगा। अगर उसके पास कुछ विचार है कि लाइनें औसतन कितनी देर तक हैं, तो वह बफर की लंबाई को अनुकूलित कर सकती है, बजाय fgetc जो बफर होगा लेकिन आदर्श बफर की लंबाई के बारे में पूरी तरह से अज्ञेयवादी होगी। –

2

यदि प्रदर्शन आपके लिए बहुत मायने रखता है, तो आप आमतौर पर fgetc के बजाय getc पर कॉल करना चाहते हैं। मानक कॉल ओवरहेड से बचने के लिए मानक मैक्रो के रूप में getc को कार्यान्वित करना आसान बनाता है।

पिछला कि, निपटने के लिए मुख्य बात शायद बफर आवंटित करने में आपकी रणनीति है। अधिकांश लोग निश्चित वृद्धि का उपयोग करते हैं (उदाहरण के लिए, जब हम अंतरिक्ष से बाहर निकलते हैं, तो एक और 128 बाइट आवंटित करें)। मैं इसके बजाय स्थिर कारक का उपयोग करने की सलाह दूंगा, इसलिए यदि आप अंतरिक्ष से बाहर निकलते हैं तो एक बफर आवंटित करें, कहें, पिछले आकार में 1 1/2 बार।

विशेष रूप से जब getc मैक्रो के रूप में लागू किया जाता है, तो getc और fgets के बीच का अंतर आमतौर पर काफी कम होता है, इसलिए आप अन्य मुद्दों पर ध्यान केंद्रित करने से सबसे अच्छे हैं।

+0

+1 धन्यवाद, यह मदद करता है :-) – nc3b

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