C++
C ++ स्ट्रीम
खोज…
टिप्पणियों
std::istream_iterator
का डिफ़ॉल्ट कंस्ट्रक्टर std::istream_iterator
एक इटरेटर std::istream_iterator
है जो स्ट्रीम के अंत का प्रतिनिधित्व करता है। इस प्रकार, std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(), ....
साधन में वर्तमान स्थिति से कॉपी करने के लिए ifs
समाप्त करने के लिए।
स्ट्रिंग की धाराएँ
std::ostringstream
एक ऐसा वर्ग है जिसकी वस्तुएं आउटपुट स्ट्रीम की तरह दिखती हैं (अर्थात, आप उन्हें operator<<
माध्यम से लिख सकते हैं operator<<
), लेकिन वास्तव में लेखन परिणामों को संग्रहीत करते हैं, और उन्हें स्ट्रीम के रूप में प्रदान करते हैं।
निम्नलिखित छोटे कोड पर विचार करें:
#include <sstream>
#include <string>
using namespace std;
int main()
{
ostringstream ss;
ss << "the answer to everything is " << 42;
const string result = ss.str();
}
रेखा
ostringstream ss;
ऐसी वस्तु बनाता है। इस ऑब्जेक्ट को पहली बार एक नियमित स्ट्रीम की तरह हेरफेर किया गया है:
ss << "the answer to everything is " << 42;
हालांकि, इसके बाद, परिणामी धारा इस तरह प्राप्त की जा सकती है:
const string result = ss.str();
(स्ट्रिंग result
"the answer to everything is 42"
बराबर होगा)।
यह मुख्य रूप से तब उपयोगी होता है जब हमारे पास एक वर्ग होता है जिसके लिए धारा क्रमांकन को परिभाषित किया गया है, और जिसके लिए हम एक स्ट्रिंग रूप चाहते हैं। उदाहरण के लिए, मान लीजिए कि हमारे पास कुछ वर्ग है
class foo
{
// All sort of stuff here.
};
ostream &operator<<(ostream &os, const foo &f);
foo
ऑब्जेक्ट का स्ट्रिंग प्रतिनिधित्व प्राप्त करने के लिए,
foo f;
हम उपयोग कर सकते हैं
ostringstream ss;
ss << f;
const string result = ss.str();
फिर result
में foo
ऑब्जेक्ट का स्ट्रिंग प्रतिनिधित्व होता है।
किसी फ़ाइल को अंत तक पढ़ना
एक पाठ फ़ाइल लाइन-दर-पंक्ति पढ़ना
अंत तक एक टेक्स्ट फ़ाइल लाइन-बाय-लाइन पढ़ने का एक उचित तरीका आमतौर पर ifstream
प्रलेखन से स्पष्ट नहीं है। आइए शुरुआत सी ++ प्रोग्रामर द्वारा की गई कुछ सामान्य गलतियों पर विचार करें, और फ़ाइल को पढ़ने का एक उचित तरीका।
बिना व्हाट्सएप के अक्षर
सरलता के लिए, मान लें कि फ़ाइल में प्रत्येक पंक्ति में कोई व्हाट्सएप प्रतीक नहीं है।
ifstream
में operator bool()
, जो तब सही होता है जब किसी स्ट्रीम में कोई त्रुटि नहीं होती है और वह पढ़ने के लिए तैयार होता है। इसके अलावा, ifstream::operator >>
स्ट्रीम के लिए एक संदर्भ देता है, इसलिए हम ईओएफ (और साथ ही त्रुटियों के लिए) एक पंक्ति में बहुत ही सुंदर वाक्य रचना के साथ पढ़ सकते हैं और जांच सकते हैं:
std::ifstream ifs("1.txt");
std::string s;
while(ifs >> s) {
std::cout << s << std::endl;
}
व्हाट्सएप पात्रों के साथ लाइनें
ifstream::operator >>
स्ट्रीम को तब तक पढ़ता है जब तक कोई व्हाट्सएप चरित्र नहीं होता है, इसलिए उपरोक्त कोड अलग-अलग लाइनों पर एक लाइन से शब्दों को प्रिंट करेगा। पंक्ति के अंत तक सब कुछ पढ़ने के लिए, std::getline
ifstream::operator >>
बजाय std::getline
उपयोग करें। getline
ने उस थ्रेड का संदर्भ दिया जिसमें उसने काम किया था, इसलिए समान सिंटैक्स उपलब्ध है:
while(std::getline(ifs, s)) {
std::cout << s << std::endl;
}
जाहिर है, अंत तक सिंगल-लाइन फ़ाइल पढ़ने के लिए भी std::getline
उपयोग किया जाना चाहिए।
एक बार में एक फ़ाइल को एक बफर में पढ़ना
अंत में, व्हाट्सएप और न्यूलाइन्स सहित किसी भी चरित्र पर रोक के बिना, शुरुआत से अंत तक फ़ाइल को पढ़ते हैं। यदि हम जानते हैं कि सटीक फ़ाइल का आकार या लंबाई का ऊपरी भाग स्वीकार्य है, तो हम स्ट्रिंग का आकार बदल सकते हैं और फिर पढ़ सकते हैं:
s.resize(100);
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
s.begin());
अन्यथा, हमें प्रत्येक वर्ण को स्ट्रिंग के अंत तक सम्मिलित करने की आवश्यकता है, इसलिए std::back_inserter
को हमारी आवश्यकता है:
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::back_inserter(s));
वैकल्पिक रूप से, स्ट्रीम डेटा के साथ एक कंस्ट्रक्टर का उपयोग करके स्ट्रीम डेटा के साथ एक संग्रह को आरंभीकृत करना संभव है:
std::vector v(std::istreambuf_iterator<char>(ifs),
std::istreambuf_iterator<char>());
ध्यान दें कि इन उदाहरणों यदि भी लागू होते हैं ifs
बाइनरी फ़ाइल के रूप में खोला गया है:
std::ifstream ifs("1.txt", std::ios::binary);
नकल करने वाली धाराएँ
धाराओं और पुनरावृत्तियों के साथ एक फ़ाइल को दूसरी फ़ाइल में कॉपी किया जा सकता है:
std::ofstream ofs("out.file");
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::ostream_iterator<char>(ofs));
ofs.close();
या संगत इंटरफ़ेस के साथ किसी अन्य प्रकार की स्ट्रीम पर पुनर्निर्देशित। उदाहरण के लिए Boost.Asio नेटवर्क स्ट्रीम:
boost::asio::ip::tcp::iostream stream;
stream.connect("example.com", "http");
std::copy(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(),
std::ostream_iterator<char>(stream));
stream.close();
Arrays
जैसा कि पुनरावृत्तियों को संकेत के सामान्यीकरण के रूप में माना जा सकता है, ऊपर के उदाहरणों में एसटीएल कंटेनरों को देशी सरणियों से बदला जा सकता है। यहाँ सरणी में संख्याओं को पार्स करने का तरीका बताया गया है:
int arr[100];
std::copy(std::istream_iterator<char>(ifs), std::istream_iterator<char>(), arr);
बफ़र ओवरफ़्लो से सावधान रहें, क्योंकि सरणियों को आवंटित किए जाने के बाद उन्हें मक्खी पर आकार नहीं दिया जा सकता है। उदाहरण के लिए, यदि ऊपर दिया गया कोड 100 से अधिक पूर्णांक संख्या वाली फ़ाइल से खिलाया जाएगा, तो यह सरणी के बाहर लिखने और अपरिभाषित व्यवहार में चलाने का प्रयास करेगा।
Iostream के साथ मुद्रण संग्रह
मूल मुद्रण
std::ostream_iterator
बिना किसी स्पष्ट धारा के किसी भी आउटपुट स्ट्रीम में STL कंटेनर की सामग्री को प्रिंट करने की अनुमति देता है। std::ostream_iterator
का दूसरा तर्क std::ostream_iterator
कंस्ट्रक्टर std::ostream_iterator
सेट करता है। उदाहरण के लिए, निम्न कोड:
std::vector<int> v = {1,2,3,4};
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ! "));
छप जाएगा
1 ! 2 ! 3 ! 4 !
निहित प्रकार की डाली
std::ostream_iterator
कंटेनर की सामग्री को निहित करने की अनुमति देता है। उदाहरण के लिए, आइए धुन std::cout
दशमलव बिंदु के बाद 3 अंकों के साथ फ्लोटिंग-पॉइंट मान मुद्रित करने के लिए:
std::cout << std::setprecision(3);
std::fixed(std::cout);
और तात्कालिक std::ostream_iterator
float
साथ, जबकि निहित मान int
रहते हैं:
std::vector<int> v = {1,2,3,4};
std::copy(v.begin(), v.end(), std::ostream_iterator<float>(std::cout, " ! "));
तो पैदावार के ऊपर कोड
1.000 ! 2.000 ! 3.000 ! 4.000 !
std::vector
बावजूद std::vector
int
एस।
सृजन और परिवर्तन
std::generate
, std::generate_n
और std::transform
फ़ंक्शंस ऑन-द-फ्लाई डेटा हेरफेर के लिए एक बहुत शक्तिशाली उपकरण प्रदान करते हैं। उदाहरण के लिए, वेक्टर होना:
std::vector<int> v = {1,2,3,4,8,16};
हम आसानी से प्रत्येक तत्व के लिए "एक्स इज़ इज़" स्टेटमेंट के बूलियन मूल्य को प्रिंट कर सकते हैं:
std::boolalpha(std::cout); // print booleans alphabetically
std::transform(v.begin(), v.end(), std::ostream_iterator<bool>(std::cout, " "),
[](int val) {
return (val % 2) == 0;
});
या वर्ग तत्व मुद्रित करें:
std::transform(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "),
[](int val) {
return val * val;
});
मुद्रण एन अंतरिक्ष-सीमांकित यादृच्छिक संख्या:
const int N = 10;
std::generate_n(std::ostream_iterator<int>(std::cout, " "), N, std::rand);
Arrays
पाठ फ़ाइलों को पढ़ने के बारे में अनुभाग में, इन सभी विचारों को मूल सरणियों पर लागू किया जा सकता है। उदाहरण के लिए, आइए एक मूल सरणी से वर्ग मान मुद्रित करें:
int v[] = {1,2,3,4,8,16};
std::transform(v, std::end(v), std::ostream_iterator<int>(std::cout, " "),
[](int val) {
return val * val;
});
पार्सिंग फाइलें
STL कंटेनरों में फ़ाइल पार्स करना
istream_iterator
s कोड में स्पष्ट छोरों के बिना एसटीएल कंटेनरों में संख्याओं या अन्य पार्सबल डेटा के दृश्यों को पढ़ने के लिए बहुत उपयोगी हैं।
स्पष्ट कंटेनर आकार का उपयोग करना:
std::vector<int> v(100);
std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
v.begin());
या पुनरावृत्ति डालने के साथ:
std::vector<int> v;
std::copy(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
std::back_inserter(v));
ध्यान दें कि इनपुट फ़ाइल में नंबर किसी भी व्हाट्सएप वर्ण और newlines की किसी भी संख्या से विभाजित हो सकते हैं।
विषम पाठ तालिकाओं को पार्स करना
के रूप में istream::operator>>
एक खाली स्थान के प्रतीक जब तक पाठ पढ़ता है, उस में इस्तेमाल किया जा सकता while
जटिल डेटा तालिकाओं पार्स करने के लिए शर्त। उदाहरण के लिए, यदि हमारे पास प्रत्येक पंक्ति में स्ट्रिंग (बिना रिक्त स्थान) के बाद दो वास्तविक संख्याओं वाली एक फ़ाइल है:
1.12 3.14 foo
2.1 2.2 barr
इसे इस तरह पार्स किया जा सकता है:
std::string s;
double a, b;
while(ifs >> a >> b >> s) {
std::cout << a << " " << b << " " << s << std::endl;
}
परिवर्तन
किसी भी रेंज-मैनिपुलेटिंग फ़ंक्शन का उपयोग std::istream_iterator
पर्वतमाला के साथ किया जा सकता है। उनमें से एक std::transform
, जो डेटा को ऑन-द-फ्लाई प्रोसेस करने की अनुमति देता है। उदाहरण के लिए, पूर्णांक मान पढ़ें, उन्हें 3.14 से गुणा करें और परिणाम को फ्लोटिंग-पॉइंट कंटेनर में संग्रहीत करें:
std::vector<double> v(100);
std::transform(std::istream_iterator<int>(ifs), std::istream_iterator<int>(),
v.begin(),
[](int val) {
return val * 3.14;
});