सी ++ में सीआईएन से ईओएफ तक कैसे पढ़ा जाए

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

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

67

10 उत्तर

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

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

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

59
जोड़ा
यहां पर सावधान रहना कुछ ऐसा है जब आप उन फ़ाइलों से पढ़ रहे हैं जो stdin के माध्यम से पाइप किए गए हैं, यह है कि यह और आपके द्वारा दिए गए अधिकांश उत्तरों में आपके इनपुट के अंत में एक अतिरिक्त लाइन फ़ीड शामिल होगी। सभी फाइलें लाइन फीड के साथ समाप्त नहीं होती हैं, फिर भी लूप का प्रत्येक पुनरावृत्ति धारा में "std :: endl" जोड़ता है। यह ज्यादातर मामलों में कोई मुद्दा नहीं हो सकता है, लेकिन अगर फ़ाइल अखंडता एक मुद्दा है, तो यह आपको वापस काटने के लिए वापस आ सकता है।
जोड़ा लेखक Zoccadoum, स्रोत
यह सबसे ऊपर जवाब नहीं होना चाहिए। नीचे समुदाय विकी उत्तर देखें। साथ ही, शायद यह प्रश्न देखें: stackoverflow.com/questions/3203452/…
जोड़ा लेखक loxaxs, स्रोत

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

#include 
#include 
#include 
#include 
#include 

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 it(std::cin);
  std::istream_iterator end;
  std::string results(it, end);

  std::cout << results;
}
43
जोड़ा
अच्छा लगा। "मुझे यकीन है कि यह आंतरिक रूप से किसी प्रकार का पाश का उपयोग करता है" - कोई भी समाधान होगा।
जोड़ा लेखक Michael Burr, स्रोत
यह इनपुट से न्यूलाइन वर्णों को हटाने के लिए प्रतीत होता है, भले ही वे बीच में सही हों।
जोड़ा लेखक Multisync, स्रोत

लूप का उपयोग करना:

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

संसाधन

37
जोड़ा

std :: istream_iterator का उपयोग करके कीथबी के समाधान की खोज करने के बाद, मैंने < कोड> एसटीडी: istreambuf_iterator

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

#include 
#include 
#include 

int main()
{
  std::istreambuf_iterator begin(std::cin), end;
  std::string s(begin, end);
  std::cout << s;
}
16
जोड़ा
यह शायद कैनोलिक जवाब होना चाहिए।
जोड़ा लेखक Kerrek SB, स्रोत
Downvoted। तो कीथबी के समाधान की तुलना में पेशेवर या विपक्ष क्या हैं? हां, आप std :: istream_iterator के बजाय std :: istreambuf_iterator का उपयोग कर रहे हैं, लेकिन इसके लिए क्या?
जोड़ा लेखक Multisync, स्रोत

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

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

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

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

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

2
जोड़ा

दुखद पक्ष नोट: मैंने बूस्ट आधारित कोड के अनुरूप होने के लिए सी ++ आईओ का उपयोग करने का निर्णय लिया। इस प्रश्न के उत्तर से मैंने जबकि (std :: getline (std :: cin, line) चुना है) । Cygwin (mintty) में g ++ संस्करण 4.5.3 (-O3) का उपयोग करके मुझे 2 एमबी/एस थ्रूपुट मिला। माइक्रोसॉफ्ट विजुअल सी ++ 2010 (/ ओ 2) ने इसे उसी कोड के लिए 40 एमबी/एस बनाया है।

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

2
जोड़ा
शुद्ध कोड को अपने कोड को फिर से लिखने की आवश्यकता नहीं है, बस अपने समय-लूप से पहले std :: iOS :: sync_with_stdio (false); जोड़ें। cin.tie (NULL); अगर आप पढ़ने और लिखने में हस्तक्षेप करते हैं तो भी मदद कर सकते हैं।
जोड़ा लेखक R D, स्रोत
while(std::cin) {
//do something
}
1
जोड़ा
यह एक उत्तर का एक भयानक आपदा है, क्योंकि यह गलत कोड में परिणामस्वरूप गारंटीकृत है।
जोड़ा लेखक Kerrek SB, स्रोत

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

std::vector data;

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

std::copy(std::istream_iterator(std::cin),
    std::istream_iterator(),
    std::back_inserter(data));

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

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

    /* process data */

    data.clear();
}
0
जोड़ा

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

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

// 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
जोड़ा