2010-04-30 15 views
8

जैसा कि आप सभी जानते हैं कि iostream और fstream जैसी धाराओं का उपयोग करके पुस्तकालय हैं।क्यों सी ++ में धाराएं?

मेरा प्रश्न है:

  • क्यों धाराओं? वे print, fgets और उदाहरण के लिए (उदाहरण के लिए) जैसे कार्यों के साथ क्यों नहीं चिपके?

वे अपने स्वयं के ऑपरेटरों << और >> की आवश्यकता होती है लेकिन सभी वे करते हैं इसके बाद के संस्करण की तरह साधारण कार्यों में लागू किया जा सकता है, यह भी समारोह

printf("Hello World!"); 

तुलना में बहुत अधिक पठनीय और मेरे लिए तार्किक है
cout << "Hello World"; 

मुझे यह भी लगता है कि सी ++ में उन सभी स्ट्रिंग अबास्ट्रक्शन सभी बाइनरी में मानक फ़ंक्शन कॉल (कम कुशल) से संकलित होते हैं।

+2

क्षमता वास्तव में कोई चिंता नहीं है, क्योंकि 99% समय एक ही ओएस कॉल में कंसोल पर प्रिंट करने के लिए कॉल किया जाएगा –

+2

क्या स्ट्रिंग अबास्ट्रक्शन? –

+2

-1 हे लड़का, मुझे लगता है कि आप सी ++ दुनिया में शुरुआत कर रहे हैं। आप कैसे कह सकते हैं कि यदि आप नहीं जानते हैं तो यह कम कुशल है? आलोचना से पहले, कृपया सीखें, और विनम्र रहें। –

उत्तर

24

स्ट्रीम में बेहतर प्रकार की सुरक्षा है।

उदाहरण के लिए printf("%s", a);a एक पूर्णांक है तो बहुत गलत हो सकता है। cout << a; में यह समस्या नहीं है।

एक और मुद्दा यह है कि धाराएं ऑब्जेक्ट ओरिएंटेड डिजाइन पद्धतियों के अनुरूप बेहतर होती हैं।

उदाहरण के लिए आपके पास एक साधारण एप्लिकेशन है जो कुछ आउटपुट लिखता है और फिर आप चाहते हैं कि आउटपुट कंसोल की बजाय फ़ाइल पर जाए। सी कॉल के साथ आपको fprintf पर कॉल करने के लिए सभी कॉलों को printf पर प्रतिस्थापित करना होगा और रास्ते में FILE* को बनाए रखने के लिए सावधानी बरतनी होगी। धाराओं के साथ आप सिर्फ धारा आप उपयोग कर रहे हैं ठोस वर्ग बदल सकते हैं और है कि यह, कोड के सबसे एक ही इसलिए की तरह बनी हुई है है:

void doSomething(ostream& output) 
{ 
    output << "this and that" << a; 
} 

doSomething(cout); 
doSomething(ofstream("c:\file.txt")); 
+1

हा हा" बेहद गलत ", इतना सच, इतना सच है। –

+0

बेशक, आधुनिक कंपाइलरों को * printf प्रारूप तारों के प्रकार की जांच का समर्थन करने के लिए (मानकों के अनुरूप तरीके से नहीं) बढ़ा दिया गया है। –

+0

"सी कॉल के साथ आपको सभी कॉलों को fprintf पर कॉल करने के लिए printf में बदलना होगा" - स्थिति इतनी खराब नहीं है, उदा। आप स्ट्रीम फ्रीपेन ("output.txt", "w", stdout) के पुनर्निर्देशन कर सकते हैं; और प्रतिस्थापन से बचें – Tebe

7

सी ++ धाराएं सुरक्षित हैं। सी में, यदि आप कहते हैं:

double d = 1.23; 
printf("%d", d); 

आपको त्रुटि संदेश प्राप्त करने की गारंटी नहीं है, भले ही रूपांतरण गलत है।

आप बहुत बुनियादी सी ++ प्रश्न पूछ रहे हैं। आप किस सी ++ टेक्स्ट बुक का उपयोग कर रहे हैं जो उन्हें कवर नहीं करता है?

2

स्ट्रीम एक साथ श्रृंखलित जा सकती है

cout << "hello" << " " << "world" 
+1

तो विधियां हो सकती हैं: out.print ("हैलो")। प्रिंट ("")। प्रिंट ("दुनिया") –

+2

'std :: cout.operator << (" हैलो ") ऑपरेटर << (" ") । ऑपरेटर << ("दुनिया"); ' –

5

printf एक के लिए सुरक्षित टाइप नहीं है। कोउट इंटरफ़ेस भी अधिक सामान्य है, जो प्रिंटफ संस्करण के साथ पूरी चीजों को अनुपलब्ध करता है। एक महान उदाहरण यह है कि आपके प्रकार के लिए आपका स्ट्रीम ऑपरेटर है, यदि आप इसे सही कर रहे हैं, तो स्ट्रीम के रूप में std :: ostream को संदर्भित करें, न कि cout। इस प्रकार आप एक अलग स्ट्रीम का उपयोग करके आउटपुट का गंतव्य बदल सकते हैं। प्रिंटफ के साथ ऐसा करने के लिए आपको आउटपुट हैंडल के प्लेटफॉर्म पर निर्भर ओवरराइटिंग का एक बहुत सारे प्लेटफॉर्म करना होगा।

मुझे यह भी लगता है कि सी ++ में उन सभी स्ट्रिंग अबास्ट्रक्शन सभी बाइनरी में मानक फ़ंक्शन कॉल (कम कुशल) से संकलित होते हैं।

जो भी आप चाहते हैं सोचें। जब तक आप वास्तव में अपनी धारणा का परीक्षण नहीं करते हैं, तब तक आपकी राय अधिक वजन नहीं रखेगी। इसके अलावा आपको अमूर्तता के नुकसान पर विचार करने की आवश्यकता है, जो आमतौर पर आधुनिक सॉफ्टवेयर विकास में एक बहुत अधिक महत्वपूर्ण है।

1

operator<< और operator>> के साथ वाक्यविन्यास जैसी स्ट्रीम अच्छी संगतता की अनुमति देती है।

printf("%d%d%d%d%d", a, b, c, d, e); 

बनाम

cout << a << b << c << d << e; 

पहले दृष्टिकोण हमेशा प्रकार के बारे में सोचना चाहिए, जबकि धारा दृष्टिकोण में, प्रकार निर्दिष्ट नहीं किया जाना चाहिए में इसके अलावा।

1
असल

cout << "Test: " << test << endl; 

एक बहुत अधिक के लिए सहज लगता है मुझसे ज्यादा

printf("Test: %d\n", test); 

इससे पहले कि आप एक printf लगते हैं कभी नहीं चाहते हैं, तो कोई रास्ता नहीं आप को पता है कि क्या करता जा रहे है।

या तो मामले में,

print "Test: " + test 

(कई भाषाओं अजगर :(सहित) बनाता है एक बहुत अधिक भावना :)

+0

पायथन के पास 'प्रिंट' टेस्ट है:% d "% test' भी, और यह अधिक जटिल स्वरूपण के लिए बहुत जरूरी है। – UncleBens

+0

@UncleBens: सच है, और यह बहुत दुर्भाग्यपूर्ण है कि उन्होंने सी-शैली प्रारूप-तारों का उपयोग करना चुना, * विशेष रूप से * गतिशील भाषा के लिए टाइपिंग की आवश्यकता होती है ... –

+0

यदि आपने पहले कभी सी ++ धाराएं नहीं देखी हैं, तो इससे भी बदतर: आपको लगता है कि आप कुछ पागल बिट स्थानांतरण कर रहे हैं! –

9

एक के लिए, यह आप का लाभ लेने के लिए अनुमति देता है सी ++ ऑब्जेक्ट मॉडल उन कार्यों को बनाने के लिए जो परवाह नहीं करते हैं कि वे मानक आउटपुट, फ़ाइल या नेटवर्क सॉकेट पर लिख रहे हैं (यदि आपके पास नेटवर्क सॉकेट है जो ostream से प्राप्त होता है)। जैसे

void outputFoo(std::ostream& os) 
{ 
    os << "Foo!"; 
} 

int main() 
{ 
    outputFoo(std::cout); 

    std::ofstream outputFile("foo.txt"); 
    outputFoo(outputFile); 

    MyNetworkStream outputSocket; 
    outputFoo(outputSocket); 
} 

और इसी तरह इनपुट स्ट्रीम के लिए।

ऑब्जेक्ट्स को इनपुट करने और आउटपुट करने की बात आने पर भी स्ट्रीम का लाभ होता है। यदि आप किसी ऑब्जेक्ट में scanf के साथ पढ़ना चाहते हैं तो क्या होगा?

MyObject obj; 
scanf("??", &obj); // What specifier to use? 

यहां तक ​​कि अगर वहाँ एक उचित विनिर्देशक थे, कैसे scanf पता होगा कैसे वस्तु के सदस्यों को भरने के लिए? सी ++ धाराओं के साथ, आप operator<< ओवरलोड और लिखने

MyObject obj; 
std::cin >> obj; 

और यह काम करेंगे कर सकते हैं। इसी तरह std::cout << obj के लिए, इसलिए आप ऑब्जेक्ट सीरियलाइजेशन कोड को एक ही स्थान पर लिख सकते हैं और इसके बारे में चिंता करने की ज़रूरत नहीं है।

+0

'ओस्ट्रीम' से प्राप्त एक नेटवर्क सॉकेट सचमुच कुछ है जो मैं देखना चाहता हूं :) – shoosh

+5

@Shoosh 'boost :: asio :: ip :: tcp :: iostream'? – Cubbi

1

सी ++ आपको रास्ते में प्रिंटफ का उपयोग करने देता है। तो अगर आपको वह पसंद है, तो आगे बढ़ें और इसका इस्तेमाल करें।

स्ट्रीम का उपयोग कंसोल पर आउटपुट लिखने से बहुत अधिक के लिए किया जाता है। वे एक सामान्य उद्देश्य डेटा बफरिंग समाधान हैं जिन्हें स्क्रीन आउटपुट से लेकर नेटवर्क यातायात और इनपुट डिवाइस इंटरफेस में फ़ाइल हैंडलिंग से सब कुछ पर लागू किया जा सकता है। आपकी सामग्री वास्तव में जाने के लिए कहां जा रही है, इस परवाह किए बिना स्ट्रीम (या पढ़ी) से लिख सकते हैं।

कहें कि आपके पास एक जटिल ऑब्जेक्ट है जिसे आप आउटपुट कंसोल, लॉग फ़ाइल में और डिबगिंग विंडो पॉपअप में लिखने में सक्षम होना चाहते हैं। क्या आप तीन कार्यों को लिखने जा रहे हैं जो लगभग एक ही चीज़ करते हैं, या आप एक फ़ंक्शन लिखने जा रहे हैं जिसमें आप एक (वाई) आउटपुट स्ट्रीम पास करते हैं?

2

धाराओं का एक और लाभ यह है कि उन्हें विस्तार योग्य बनाया गया था। नदियों के साथ, आप अपने उपयोगकर्ता परिभाषित कक्षाओं काम सिर्फ प्रकार में बनाया गया पसंद हो सकते हैं:

class foo { ... }; 

ostream &operator<<(ostream &ostr, const foo &f) 
{ 
    ostr << ... how you want to print a foo ...; 
    return ostr; 
} 

और अब आप कुछ और की तरह एक foo मुद्रित कर सकते हैं: जिसका मुख्य कारण

int n = ... 
foo f = ... 

cout << n << ": " << f << endl; 
0

मैं अभी भी printf का उपयोग, आउटपुट प्रारूप को नियंत्रित करना आसान है।

मेरे लिए, सुरक्षा यहां मुख्य लाभ नहीं है क्योंकि इसे आसानी से परीक्षण द्वारा पकड़ा जा सकता है, इस तथ्य के मुताबिक कि कंसोल आधारित प्रोग्राम UI आधारित या वेब आधारित अनुप्रयोगों के साथ परीक्षण करने के लिए कहीं अधिक आसानी से है। यदि आप परीक्षण नहीं करते हैं, तो संकलन समय पर अधिक गंभीर बग किसी भी तरह से जांच सकते हैं।

मैं किसी अन्य कारण से भी सहमत नहीं हूं कि विच्छेदन प्रवाह के कारण दावा अधिक लचीला है। यह विनिमयशीलता के लिए fprintf (fout, ...) का उपयोग करने की अनुशंसा करने के बराबर है। यदि आपको आउटपुट रीडायरेक्ट करने की आवश्यकता है, तो पाइप का उपयोग करें। यदि आप लाइब्रेरी में हैं, तो आप केवल एक स्ट्रिंग क्यों नहीं लौटते हैं और कॉलर को यह तय करने दें कि यह कहां जाता है?

+0

एक पाइप का उपयोग करें - सबकुछ एप्लिकेशन की तरह कमांड नहीं है। एक स्ट्रिंग लौटें - बहुत कुशल नहीं। – shoosh

+1

शूश, जिज्ञासा से, आप फ़ंक्शन से सी में स्ट्रिंग कैसे वापस कर सकते हैं? मेरा मतलब है कि अगर इसे वहां आवंटित किया गया था (स्थिर चार * mystring), तो आप केवल एक सूचक लौटाएंगे। यदि आप एसटीएल से स्ट्रिंग का मतलब रखते हैं तो आप स्ट्रिंग का प्रतिनिधित्व करने वाली केवल ऑब्जेक्ट लौटाते हैं, स्ट्रिंग कहीं और होती है - प्रभावशीलता में कोई कमी नहीं होती है – Tebe

3

सुरक्षित और पॉलिमॉर्फिक प्रकार होने के अलावा, धाराएं अधिक पोर्टेबल हैं। कुछ सिस्टम प्रिंटर पर लंबे समय तक "% d" की आवश्यकता होती है और कुछ सिस्टमों पर इसे "% ld" की आवश्यकता होती है।

+0

अनुपालन हमेशा '% ld' की आवश्यकता होती है, लेकिन 'एल' कुछ प्लेटफ़ॉर्म पर कुछ भी नहीं करता है। – Potatoswatter

+0

मैंने कभी भी इसे समझने के बिना धाराओं का उपयोग करने के लिए इस पर काम करने के लिए बहुत जटिल, पागल कोड बदल दिया है! –

+0

+1 एक दिन मैं लंबे समय तक खो गया था जब तक कि मैं देखने के लिए डीबगर का उपयोग नहीं करता – Tebe

0

stringstreamsnprintf/sscanf से सुरक्षित है क्योंकि यह पूरी तरह से बफर ओवरफ़्लो (यहां तक ​​कि "सुंदर विफलताओं") की संभावना से बचाता है।

0

स्ट्रीम टेम्पलेट्स के साथ काम करते हैं, जबकि printf/scanf नहीं करते हैं।

2

सी ++ आईओएसट्रीम हास्यास्पद रूप से अक्षम हैं (अधिकांश कार्यान्वयन में मुझे पता है)। अक्सर, यह कोई चिंता नहीं है, लेकिन जब यह है, पुस्तकालय मूल रूप से बेकार है। यह भी एक अच्छा मुद्दा है कि वाक्यविन्यास अनजान (और बहुत, बहुत verbose) है। लाइब्रेरी जटिल और विस्तार करने के लिए अनिवार्य रूप से कठिन है। यह या तो बहुत लचीला नहीं है। जब एसटीएल की तरह कुछ के खिलाफ विपरीत, IOStreams वास्तव में एक बुरा सपना दिखता है। लेकिन यह यहाँ है, और हम इसके साथ अटक गए हैं।

यह कारण यहां है, और ऐसा लगता है कि ऐसा लगता है, यह पहले विकसित किया गया था, सी ++ परिपक्व भाषा होने से पहले। दशकों के अनुभव से पहले हमें बता रहा था कि क्या अच्छा पुस्तकालय डिजाइन है, और नहीं। किसी को वास्तव में पता था कि विकल्प क्या थे।

सी ++ को एक आई/ओ लाइब्रेरी की आवश्यकता है जो सी 0 की तुलना में बेहतर था। और कुछ महत्वपूर्ण तरीकों से, सी ++ IOStreams बेहतर हैं। वे टाइप-सेफ और एक्स्टेंसिबल हैं जैसे कि अन्य ने उल्लेख किया है। एक ऑपरेटर को लागू करके, मैं एक उपयोगकर्ता परिभाषित वर्ग मुद्रित कर सकता हूं। यह printf के साथ नहीं किया जा सका। मुझे प्रारूप सुरक्षा की कमी की वजह से प्रारूप विनिर्देशकों को गलत और कचरा प्रिंट करने के बारे में भी चिंता करने की ज़रूरत नहीं है।

उन चीजों को को की आवश्यकता है। और हे, प्रारंभिक दिनों में, वर्चुअल फ़ंक्शंस और ऑपरेटर ओवरलोडिंग पर छिद्रित थे। यह अच्छा लग रहा था।बेशक पुस्तकालय उन सुविधाओं का उपयोग करना चाहता था।

IOStreams पुस्तकालय एक समझौता के बीच है:

  • कुछ सुरक्षित और अधिक से अधिक एक्स्टेंसिबल सी stdio.h
  • कुछ कुशल
  • कुछ अच्छी तरह से डिजाइन और सहज ज्ञान युक्त
  • एक पुस्तकालय है कि वास्तव में अस्तित्व में उस समय जब सी ++ को मानकीकृत किया जा रहा था। कि आज (वे कुछ जोड़ने के लिए किया था, तो वे उम्मीदवारों है कि वास्तव में समय मौजूद बीच चयन करने के लिए किया था।)

पुस्तकालय इन सभी को प्राप्त नहीं है, और मुझे विश्वास है, हमारे दशकों के साथ भाषा के साथ अनुभव का, हम एक बेहतर पुस्तकालय डिजाइन कर सकते थे। लेकिन 90 के दशक के मध्य में, जब वे जोड़ने के लिए आई/ओ लाइब्रेरी की तलाश में थे, तो वे सबसे अच्छे थे।

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