2014-10-03 14 views
5

में कैसे काम करता है मैं कंप्यूटर विज्ञान छात्र हूं, इसलिए सी ++ भाषा के साथ अधिक अनुभव नहीं है (यह इस भाषा का उपयोग करके मेरा पहला सेमेस्टर है) या उस मामले के लिए कोडिंग।एक्स्ट्राक्ट >> ऑपरेटर सी ++

मैं की सरल रूप में एक पाठ फ़ाइल से पूर्णांकों को पढ़ने के लिए एक काम दिया गया था:

19 3 -2 9 14 4 
5 -9 -10 3 
. 
. 
. 

यह मैं बेहतर समझने के लिए/ओ ऑपरेटरों, के बाद से मैं करने के लिए आवश्यक कर रहा हूँ एक यात्रा पर का मुझे भेजा इस स्ट्रीम के साथ कुछ चीजें (duh।)

मैं हर जगह देख रहा था और निकालने के लिए एक सरल स्पष्टीकरण नहीं मिला कि ऑपरेटर आंतरिक रूप से कैसे काम करता है। मुझे अपने प्रश्न को स्पष्ट करने दें:

मुझे पता है कि निकालने वाला >> ऑपरेटर अंतरिक्ष, टैब या न्यूलाइन हिट होने तक एक जारी तत्व निकालेगा। जो मैं समझने की कोशिश करता हूं वह है, पॉइंटर (?) या रीड-लोकेशन (?) कहां होगा, इसके बाद यह तत्व निकालेगा। क्या यह तत्व के अंतिम भाग पर हटा दिया जाएगा या इसे हटा दिया गया था और इसलिए चला गया? क्या यह अंतरिक्ष/टैब/'\ n' चरित्र पर ही होगा? शायद निकालने के लिए अगले तत्व की शुरुआत?

मुझे उम्मीद है कि मैं काफी स्पष्ट था। मेरी समस्या स्पष्ट करने के लिए मुझे सभी उचित शब्दकोष की कमी है। (मामले में किसी को भी सोच रहा है ...) आवश्यकताओं में से एक अलग से प्रत्येक पंक्ति में सभी पूर्णांकों योग करने के लिए है:


यहाँ कारण है कि मैं इस पता करने की जरूरत है। मैंने फ़ाइल के अंत तक पहुंचने तक सभी इंटीग्रियों को एक-एक करके निकालने के लिए एक लूप बनाया है। हालांकि, मुझे जल्द ही पता चला कि निकालने >> ऑपरेटर अंतरिक्ष/टैब/न्यूलाइन को अनदेखा करता है। मैं कोशिश करना चाहता हूं >> एक तत्व निकालने के लिए, और फिर space/tab/newline प्राप्त करने के लिए inputFile.get() का उपयोग करें। फिर, अगर यह एक नई लाइन है, तो मुझे जो करना है वह करो। यह केवल तभी काम करेगा जब स्ट्रीम पॉइंटर अंतिम निष्कर्षण के बाद स्पेस/टैब/न्यूलाइन निकालने के लिए अच्छी स्थिति में होगा।


In my previous question, मैं getline() और एक sstring का उपयोग कर इसे हल करने की कोशिश की।


समाधान:

कैसे ऑपरेटर >> काम करता है की मेरी विशिष्ट प्रश्न का जवाब दे, के लिए, मैं सबसे अच्छा एक के रूप में बेन वोइट के जवाब को स्वीकार करने के लिए किया था। मैंने यहां सुझाए गए अन्य समाधानों का उपयोग किया है (प्रत्येक पंक्ति के लिए एक एसस्ट्रिंग का उपयोग करके) और उन्होंने काम किया! हालांकि, मैं एक और समाधान लागू (आप मेरे पिछले प्रश्न के लिंक में देख सकते हैं) बेन के जवाब का उपयोग कर और यह भी काम किया:

 . 
     . 
     . 

if(readFile.is_open()) { 
     while (readFile >> newInput) { 
       char isNewLine = readFile.get(); //get() the next char after extraction 

       if(isNewLine == '\n')    //This is just a test! 
         cout << isNewLine;   //If it's a newline, feed a newline. 
       else 
         cout << "X" << isNewLine; //Else, show X & feed a space or tab 

       lineSum += newInput; 
       allSum += newInput; 
       intCounter++; 
       minInt = min(minInt, newInput); 
       maxInt = max(maxInt, newInput); 

       if(isNewLine == '\n') { 
         lineCounter++; 
         statFile << "The sum of line " << lineCounter 
         << " is: " << lineSum << endl; 
          lineSum = 0; 
       } 
     } 
     . 
     . 
     . 

के साथ मेरी संख्यात्मक मानों के लिए कोई संबंध है, प्रपत्र सही है! दोनों रिक्त स्थान और '\ n के catched गया: test

धन्यवाद बेन वोइट :)

बहरहाल, इस समाधान बहुत प्रारूप निर्भर है और बहुत नाजुक है। यदि किसी भी पंक्ति में '\ n' (जैसे स्पेस या टैब) से पहले कुछ और है, तो कोड न्यूलाइन चार को याद करेगा। इसलिए, अन्य समाधान, getline() और sstrings का उपयोग कर, अधिक विश्वसनीय है।

+0

लगता है आप पूरी लाइनों पढ़ना चाहते हैं, और फिर उन्हें अपने आप को पार्स। – Deduplicator

+0

आप ज्यादातर अप्रासंगिक कार्यान्वयन विवरण के बारे में पूछ रहे हैं। 'ऑपरेटर >>' एक मूल्य निकालता है और धारा को आगे बढ़ाता है। यदि आप अधिक जटिल पार्सिंग चाहते हैं, तो असली पार्सर का उपयोग करें। –

+1

क्या आपने 'get' को कॉल करने और यह जांचने का प्रयास किया कि आप किस चरित्र को प्राप्त कर रहे हैं? –

उत्तर

3

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

हालांकि यह वास्तव में कोई फर्क नहीं पड़ता है, क्योंकि आप उस सफेद जगह पर छोड़ने के लिए ज़िम्मेदार नहीं हैं। अगला निष्कर्षण सफेद डेटा को तब तक अनदेखा कर देगा जब तक कि यह वैध डेटा न मिले।

सारांश में:

  • प्रमुख खाली स्थान के नजरअंदाज कर दिया है
  • पिछली श्वेत रिक्ति धारा

में छोड़ दिया है वहाँ भी है noskipws संशोधक जो डिफ़ॉल्ट व्यवहार को बदलने के लिए इस्तेमाल किया जा सकता है।

1

cppreference.com के अनुसार मानक operator>>std::num_get::get पर कार्य को प्रतिनिधि करता है। यह इनपुट इटरेटर लेता है। एक इनपुट इटरेटर के गुणों में से एक यह है कि आप इसे आगे बढ़ाने के बिना कई बार इसे कम कर सकते हैं। इस प्रकार जब एक गैर-संख्यात्मक चरित्र का पता लगाया जाता है, तो इटेटरेटर उस चरित्र को इंगित कर देगा।

+0

cppreference.com किसी और को पढ़ने के लिए इंगित करने के लिए एक अच्छी जगह है, लेकिन इसका जवाब देने के लिए इसका उत्तर गलत लगता है - यह एक अधिकार नहीं है। आपका जवाब वास्तव में मानक कहता है कि आपके जवाब में मानक से उद्धरण के लिए उचित लगता है। –

+0

जो ठीक है, लेकिन यह वास्तव में आपको नहीं बताता है कि इनपुट पॉइंटर इनपुट स्ट्रीम में कब समाप्त होगा। (ध्यान दें कि 'std :: istream_iterator' और' std :: istreambuf_iterator' के इस संबंध में अलग-अलग व्यवहार हैं।) –

+0

@BenVoigt आप अपने उत्तर के साथ आने के लिए स्वतंत्र हैं। मुझे शायद ही कभी उस चरम पर जाने की आवश्यकता महसूस होती है, जिसका मतलब है कि मैं इस पर अच्छा होने के लिए पर्याप्त अभ्यास नहीं कर रहा हूं। –

2

operator>> फ़ाइल अंतिम वर्ण निकाले (जो फ़ाइल के अंत में हो सकता है) से परे एक चरित्र में वर्तमान स्थिति छोड़ देता है। जो आपकी समस्या से जरूरी नहीं है; लाइन में अंतिम मान के बाद रिक्त स्थान या टैब हो सकते हैं। आप आगे छोड़ सकता है हर किरदार के पढ़ने और जाँच यह '\n' के अलावा किसी अन्य सफेद स्थान है, लेकिन पढ़ने लाइन उन्मुख इनपुट std::getline करने के लिए लाइन पढ़ उपयोग करने के लिए है की एक कहीं अधिक मुहावरेदार तरीका है कि क्या , तो एक std::istringstream को निकालने प्रारंभ लाइन से पूर्णांकों:

std::string line; 
while (std::getline(source, line)) { 
    std::istringstream values(line); 
    // ... 
} 

इससे यह भी सुनिश्चित पंक्ति में एक प्रारूप त्रुटि के मामले में, मुख्य इनपुट की त्रुटि राज्य अप्रभावित है कि, और आप अगली पंक्ति के साथ जारी रख सकते हैं।

+0

आपके उत्तर के लिए धन्यवाद! मैंने वास्तव में कोशिश की, लेकिन शायद इसे किसी भी तरह से गड़बड़ कर दिया [मेरे पिछले प्रश्न में] (http://stackoverflow.com/questions/26134028/not-getting-all-lines-from-a-text-file-when-using- getlin-इन-सी)। आप वहां मेरा गुंजाइश कोड पा सकते हैं। यह पहली पंक्ति को उठाता है और सही तरीके से काम करता है, और यह फ़ाइल में सभी पंक्तियों को ठीक तरह से भी पहचानता है, लेकिन उनके भीतर सभी पूर्णांक मानों को शून्य कर देगा। –

+1

@GilDekel आपके पिछले प्रश्न में सी ++ लेबल नहीं था, इसलिए जब तक मैंने लिंक का पालन नहीं किया तब तक मैंने इसे नहीं देखा। मैंने इसका उत्तर भी दिया है। प्रत्येक बार जब आप एक नई लाइन प्राप्त करते हैं तो लाइन के साथ _new_ 'std :: istringstream' बनाने की कुंजी है। –

1

सामान्यतः, istream का व्यवहार पत्थर में सेट नहीं है। किसी भी istream व्यवहारों को बदलने के लिए कई झंडे मौजूद हैं, जिन्हें आप here के बारे में पढ़ सकते हैं। आम तौर पर, आपको वास्तव में परवाह नहीं करना चाहिए कि आंतरिक सूचक कहाँ है; यही कारण है कि आप पहली जगह में एक स्ट्रीम का उपयोग कर रहे हैं। अन्यथा आप पूरी फ़ाइल को स्ट्रिंग या समकक्ष में डंप करेंगे और मैन्युअल रूप से इसका निरीक्षण करेंगे।

वैसे भी, आपकी समस्या पर वापस जाने के लिए, एक संभावित दृष्टिकोण getline विधि को istream द्वारा स्ट्रिंग निकालने के लिए प्रदान करना है। स्ट्रिंग से, आप या तो मैन्युअल रूप से इसे पढ़ सकते हैं, या इसे stringstream में परिवर्तित कर सकते हैं और वहां से टोकन निकाल सकते हैं।

उदाहरण:

std::ifstream ifs("myFile"); 
std::string str; 

while (std::getline(ifs, str)) { 
    std::stringstream ss(str); 
    double sum = 0.0, value; 
    while (ss >> value) sum += value; 
    // Process sum 
} 
+0

धन्यवाद। जैसा कि मैंने @ जेम्स कन्ज़ की प्रतिक्रिया में उल्लेख किया है, मैंने कुछ ऐसा ही प्रयास किया है [मेरे पिछले प्रश्न में।] (Http://stackoverflow.com/questions/26134028/not-getting-all-lines-from-a-text- फ़ाइल-कब-उपयोग-गेटलिन-इन-सी) हालांकि, मैंने शायद इसे मूर्खतापूर्ण तरीके से गड़बड़ कर दिया क्योंकि मैंने कभी भी एक स्ट्रिंग का उपयोग नहीं किया था। –

+1

@GilDekel मैंने आपका कोड वहां देखा है, और ऐसा लगता है कि आप इसे रीसेट करने के लिए मैन्युअल रूप से 'स्ट्रिंगस्ट्रीम' की सामग्री से गड़बड़ कर रहे हैं। जैसा कि मैंने यहां किया था, हर लूप चक्र में एक नया निर्माण करने पर विचार करें। – Svalorzen

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