E ++ में C ++ से EOF तक कैसे पढ़ें


80

मैं एक प्रोग्राम को कोड कर रहा हूं जो सीधे उपयोगकर्ता इनपुट से डेटा पढ़ता है और सोच रहा था कि मैं (बिना छोरों के) मानक इनपुट से ईओएफ तक सभी डेटा कैसे पढ़ सकता हूं। मैं उपयोग करने cin.get( input, '\0' )पर विचार कर रहा था लेकिन '\0'वास्तव में ईओएफ चरित्र नहीं है, जो कि केवल ईओएफ तक पढ़ता है या '\0', जो भी पहले आता है।

या यह करने का एकमात्र तरीका छोरों का उपयोग कर रहा है? यदि हां, तो सबसे अच्छा तरीका क्या है?

जवाबों:


78

आप जिस तरह से डेटा की एक परिवर्तनीय राशि को पढ़ सकते हैं stdinउसका एकमात्र तरीका लूप्स का उपयोग करना है। मैंने हमेशा पाया है कि std::getline()फ़ंक्शन बहुत अच्छी तरह से काम करता है:

std::string line;
while (std::getline(std::cin, line))
{
    std::cout << line << std::endl;
}

डिफ़ॉल्ट रूप getline()से एक नई पंक्ति तक पढ़ता है। आप एक वैकल्पिक समाप्ति वर्ण निर्दिष्ट कर सकते हैं, लेकिन ईओएफ स्वयं एक चरित्र नहीं है, इसलिए आप केवल एक कॉल नहीं कर सकते getline()


8
यहाँ से सावधान रहने की बात यह है कि जब आप उन फाइलों से पढ़ रहे होते हैं जिन्हें स्टड के माध्यम से पाइप किया गया होता है, तो यह है कि यह और दिए गए अधिकांश उत्तर आपके इनपुट के अंत में एक अतिरिक्त लाइन फीड को जोड़ देंगे। सभी फ़ाइलें एक पंक्ति फ़ीड के साथ समाप्त नहीं होती हैं, फिर भी लूप का प्रत्येक पुनरावृत्ति धारा में "std :: endl" जोड़ देता है। यह ज्यादातर मामलों में एक मुद्दा नहीं हो सकता है, लेकिन अगर फ़ाइल अखंडता एक मुद्दा है, तो यह आपको काटने के लिए वापस आ सकता है।
जोकाडॉउम

1
यह सबसे उत्कट उत्तर नहीं होना चाहिए। नीचे दिए गए समुदाय विकि उत्तर को देखें। इसके अलावा, शायद यह प्रश्न देखें: stackoverflow.com/questions/3203452/…
loxaxs

52

छोरों का उपयोग करना:

#include <iostream>
using namespace std;
...
// numbers
int n;
while (cin >> n)
{
   ...
}
// lines
string line;
while (getline(cin, line))
{
   ...
}
// characters
char c;
while (cin.get(c))
{
   ...
}

संसाधन


50

आप स्ट्रीम पुनरावृत्तियों का उपयोग करके स्पष्ट छोरों के बिना कर सकते हैं। मुझे यकीन है कि यह आंतरिक रूप से कुछ प्रकार के लूप का उपयोग करता है।

#include <string>
#include <iostream>
#include <istream>
#include <ostream>
#include <iterator>

int main()
{
// don't skip the whitespace while reading
  std::cin >> std::noskipws;

// use stream iterators to copy the stream to a string
  std::istream_iterator<char> it(std::cin);
  std::istream_iterator<char> end;
  std::string results(it, end);

  std::cout << results;
}

3
अच्छा लगा। जैसा कि "मुझे यकीन है कि यह आंतरिक रूप से कुछ प्रकार के लूप का उपयोग करता है" - कोई भी समाधान होगा।
माइकल बूर

ऐसा लगता है कि इनपुट से न्यूलाइन वर्ण हटा दिए गए हैं, भले ही वे मध्य में हों।
मल्टीसेप्स

28

कीथबी के समाधान का उपयोग करने पर शोध करने के बाद std::istream_iterator, मुझे पता चला std:istreambuf_iterator

एक स्ट्रिंग में सभी पाइप किए गए इनपुट को पढ़ने के लिए टेस्ट प्रोग्राम, फिर इसे फिर से लिखें:

#include <iostream>
#include <iterator>
#include <string>

int main()
{
  std::istreambuf_iterator<char> begin(std::cin), end;
  std::string s(begin, end);
  std::cout << s;
}

7
यह संभवतः विहित उत्तर होना चाहिए।
केरेक एसबी

2
नीचा दिखाया। तो कीथ के समाधान की तुलना में पेशेवरों या विपक्ष क्या हैं? हाँ, आप एक के std::istreambuf_iteratorबजाय का उपयोग कर रहे हैं std::istream_iterator, लेकिन क्या के लिए?
मल्टीसिप

std :: istreambuf_iterator व्हाट्सएप को डिफ़ॉल्ट रूप से छोड़ देता है और तेज हो सकता है
Sopel

5

संभावित सबसे सरल और आम तौर पर कुशल:

#include <iostream>
int main()
{
    std::cout << std::cin.rdbuf();
}

यदि आवश्यक हो, तो std::ostringstreamमानक आउटपुट स्ट्रीम के बजाय बफर जैसे अन्य प्रकार की धारा का उपयोग करें।


आप लोग पहले से ही जानते हैं, लेकिन कुछ के लिए उपयोगी हो सकता है std::ostringstream std_input; std_input << std::cin.rdbuf(); std::string s = std_input.str():। आपके पास सभी इनपुट हैं s( std::stringयदि इनपुट बहुत बड़ा है तो सावधान रहें )
Ribamar

2

आप एक पूरी लाइन प्राप्त करने के लिए std :: istream :: getline () या अधिमानतः संस्करण जो std :: string पर कार्य करते हैं, का उपयोग कर सकते हैं । दोनों में ऐसे संस्करण हैं जो आपको सीमांकक (पंक्ति वर्ण का अंत) निर्दिष्ट करने की अनुमति देते हैं। स्ट्रिंग संस्करण के लिए डिफ़ॉल्ट 'n' है।


2

दुःखद पक्ष ध्यान दें: मैंने C ++ IO का उपयोग करने का फैसला किया ताकि बढ़ावा आधारित कोड के अनुरूप हो। इस सवाल के जवाब से मैंने चुना while (std::getline(std::cin, line))। साइबरविविन (मिनिटेट) में जी ++ संस्करण 4.5.3 (-ओ 3) का उपयोग करके मुझे 2 एमबी / एस थ्रूपुट मिला। Microsoft Visual C ++ 2010 (/ O2) ने इसे समान कोड के लिए 40 MB / s बनाया।

शुद्ध सी while (fgets(buf, 100, stdin))के लिए IO को फिर से लिखने के बाद दोनों परीक्षण किए गए संकलक में थ्रूपुट 90 MB / s तक कूद गया। यह 10 एमबी से बड़े किसी भी इनपुट के लिए एक अंतर बनाता है ...


शुद्ध सी के लिए अपने कोड को फिर से लिखने की आवश्यकता नहीं है, बस std::ios::sync_with_stdio(false);अपने समय से पहले लूप जोड़ें। cin.tie(NULL);यदि आप पठन और लेखन में दखल देते हैं तो भी मदद मिल सकती है।
आरडी

0
while(std::cin) {
 // do something
}

8
यह एक उत्तर की भयानक आपदा है, क्योंकि यह लगभग गलत कोड में परिणाम की गारंटी है।
केरेक एसबी

@KerrekSB क्यों यह वास्तव में गलत कोड में परिणाम की गारंटी है?
Matusf

1
@ MatúšFerech: क्योंकि यह दृढ़ता से सुझाव देता है कि // do somethingI / O संचालन के वापसी मूल्यों के अतिरिक्त चेक शामिल नहीं हैं, और इसमें जो चेक होता है वह अर्थहीन है।
केरेके एस.बी.

0

रुको, क्या मैं आपको सही तरीके से समझ रहा हूं? आप कीबोर्ड इनपुट के लिए सिनेमा का उपयोग कर रहे हैं, और जब उपयोगकर्ता EOF वर्ण में प्रवेश करता है, तो आप इनपुट पढ़ना बंद करना चाहते हैं? उपयोगकर्ता ईओएफ चरित्र में कभी क्यों टाइप करेगा? या क्या आपका मतलब है कि आप ईओएफ में एक फ़ाइल से पढ़ना बंद करना चाहते हैं?

यदि आप वास्तव में एक ईओएफ चरित्र को पढ़ने के लिए सिनेमा का उपयोग करने की कोशिश कर रहे हैं, तो केवल ईओएफ को सीमांकक के रूप में क्यों नहीं निर्दिष्ट करें?

// Needed headers: iostream

char buffer[256];
cin.get( buffer, '\x1A' );

यदि आप ईओएफ पर एक फ़ाइल से पढ़ना बंद करने का मतलब है, तो बस गेटलाइन का उपयोग करें और एक बार फिर ईओएफ को सीमांकक के रूप में निर्दिष्ट करें।

// Needed headers: iostream, string, and fstream

string buffer;

    ifstream fin;
    fin.open("test.txt");
    if(fin.is_open()) {
        getline(fin,buffer,'\x1A');

        fin.close();
    }

0

एक विकल्प कंटेनर का उपयोग करने के लिए है, जैसे

std::vector<char> data;

और इस संग्रह में सभी इनपुट को पुनर्निर्देशित कियाEOF जाता है जब तक कि प्राप्त न हो जाए

std::copy(std::istream_iterator<char>(std::cin),
    std::istream_iterator<char>(),
    std::back_inserter(data));

हालाँकि, उपयोग किए गए कंटेनर को मेमोरी को बहुत अधिक बार वास्तविक करने की आवश्यकता हो सकती है, या std::bad_allocजब आपका सिस्टम मेमोरी से बाहर हो जाता है तो आप एक अपवाद के साथ समाप्त हो जाएंगे । इन समस्याओं को हल करने के लिए, आप तत्वों की एक निश्चित मात्रा को आरक्षित कर सकते Nहैं और इन तत्वों की मात्रा को अलग कर सकते हैं, अर्थात

data.reserve(N);    
while (/*some condition is met*/)
{
    std::copy_n(std::istream_iterator<char>(std::cin),
        N,
        std::back_inserter(data));

    /* process data */

    data.clear();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.