2013-04-24 13 views
5

मुझे इनपुट फ़ाइल से पढ़ने में परेशानी हो रही है। इनपुट फ़ाइल इसइनपुट फ़ाइल से पढ़ना

लियोनेल मेसी -10 43

फ़र्नांडो टोरेस की तरह दिखता है 9 -29

क्रिस्टियानो रोनाल्डो 7 31

वेन रूनी 10 37

नेमार 17 29

एंड्रेस इनिएस्टा 8 32

रॉबिन वैन पर्सी 19 20

लियोनेल मेसी 10 43

जावी हर्नांडेज़ 6 36

Mesut Özil 10 38

डिडिएर ड्रोग्बा 10 35

फ़र्नांडो टोरेस 9 29

काका 10 17

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

यह मेरा कोड जब im इनपुट फ़ाइल

while(!fin.eof()) 
    { 

    fin >> first >> last >> num >> point; 

    if (num > 0 && point > 0) 
    { 
      list[i].firstname = first; 
      list[i].lastname = last; 
      list[i].number = num; 
      list[i].points = point; 
      i++; 
    } 
    else if (num < 0 || point < 0) 
    { 
      reject[j].firstname = first; 
      reject[j].lastname = last; 
      reject[j].number = num; 
      reject[j].points = point; 
      j++; 
    } 

    } 

यह पूरी तरह से काम करता है, तो इनपुट एक प्रथम नाम और अंतिम नाम है से पढ़ कैसा दिखता है। मुझे पता है कि समस्या फिन >> पहले >> अंतिम >> संख्या >> बिंदु;

लेकिन मैं वास्तव में यकीन है कि कैसे पहली और आखिरी (और संभवतः मध्य) डाल करने के लिए एक साथ

+4

आह, लेकिन आप 'getline' का उपयोग कर सकते हैं। – chris

+1

क्या नाम के हिस्सों के बीच "अंतरिक्ष" समान नाम और संख्याओं के बीच समान है? अगर यह नाम और संख्याओं के बीच एक टैब वर्ण '' t'' 'है तो यह बहुत मदद करेगा। अन्यथा, आप (संभवतः) एक संपूर्ण रेखा को पढ़ना चाहते हैं, और फिर स्ट्रिंग के पीछे से संख्या बिट्स को हटाएं (उदाहरण के लिए 'std :: string :: find_last_of' और' std :: string :: substr' का उपयोग करके) –

+0

हां सभी रिक्त स्थान नाम और संख्याओं के बीच समान हैं। तो पूरी लाइन को एक स्ट्रिंग वेरिएबल में स्टोर करना संभव है, और फिर स्ट्रिंग के अंत से दो संख्याओं को हटा दें और उन्हें अलग-अलग चर में रखें? – kylekolossus

उत्तर

0

असल में, आप getline उपयोग कर सकते हैं() नहीं हूँ, दो पैरामीटर विधि का प्रयोग करें, इसे एक स्ट्रीम और '\ n' को डिलीमीटर के रूप में पास करें।

पूरी लाइन को एक स्ट्रिंग में असाइन करें, फिर एक स्थान का उपयोग करके एक स्थान का उपयोग करके स्ट्रिंग को विभाजित करें, और दूसरे दो को पूर्णांक में घुमाएं।

+0

स्पेस रिक्त स्थान पर विफल रहता है नाम में (जो प्रति नाम परिवर्तनीय है) –

+0

पते के लिए अद्यतन उत्तर। –

+0

@MichaelDorgan यह अभी भी इस तरह से संभव है ... अंतिम दो तत्वों को पूर्णांक और अन्य सभी तत्वों (चाहे कितने भी हो) नाम के रूप में उपयोग करें। प्रत्येक नाम के बाद पूर्णांक पूर्णांक है। –

4

आप लाइनों को निकालने के लिए std::getline का उपयोग कर सकते हैं, स्पेस अलग शब्दों के std::vector में लाइन को पार्स करें। फिर आप जानते हैं कि शब्द के words.size() - 2 नाम का हिस्सा हैं। उदाहरण के लिए:

std::fstream in("in.txt"); 
std::string line; 

// Extract each line from the file 
while (std::getline(in, line)) { 
    std::istringstream line_stream(line); 

    // Now parse line_stream into a vector of words 
    std::vector<std::string> words(std::istream_iterator<std::string>(line_stream), 
           (std::istream_iterator<std::string>())); 

    int name_word_count = words.size() - 2; 
    if (name_word_count > 0) { 
    // Concatenate the first name_word_count words into a name string 
    // and parse the last two words as integers 
    } 
} 
+0

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

+0

@ जेम्सस्केज़ एचएम, मुझे आश्चर्य है कि यह क्यों हो रहा था। निश्चित रूप से पहला तर्क संभव नहीं हो सकता है (इसमें 'line_stream' है)? –

+0

' line_stream' का अर्थ समझा जाएगा पहले पैरामीटर का नाम –

0

1.) फ़ाइल

std::ifstream myFile("somewhere.txt"); 

2.) देखने के लिए खोलें यदि फ़ाइल खुला

if(myFile.is_open()) 

3 है।) फ़ाइल

while(!myFile.eof()) 

4. के अंत तक पढ़ें) एक प्रथम नाम सरणी

myFile >> firstName[numberOfPeople]; 

5.) में पहला नाम पढ़ें अंतिम नाम सरणी

myFile >> lastName[numberOfPeople]; 
में अंतिम नाम पढ़ें

6.) एक पूर्णांक सरणी में पूर्णांक पढ़ें

myFile >> integer[numberOfPeople]; 

7.) लोगों

numberOfPeople++; 

8.) जब जबकि किया जाता है की वृद्धि संख्या, पास फ़ाइल

myFile.close(); 

9.) तो फ़ाइल नहीं खुला था, त्रुटि की सूचना देती।

else 
    std::cout << "\nFile did not open. " << std::endl; 

आप गेटलाइन फ़ंक्शन का उपयोग कर सकते हैं, आपको केवल स्ट्रिंग को पार्स करना होगा। यह strtok का उपयोग करके हासिल किया जा सकता है।

+2

आप कभी भी 'strtok' का उपयोग नहीं करना चाहते हैं। –

+0

और आपको वास्तव में नज़दीक की आवश्यकता नहीं है। (आप आउटपुट के लिए करते हैं, क्योंकि आपको यह जांचना है कि यह सफल होता है, लेकिन इनपुट के लिए, आप नहीं करते हैं।) –

+2

और फिर "इस धागे में खराब कोड": 'जबकि (! MyFile.eof())' निश्चित रूप से एक है त्रुटि, और बहुत बुरा कोड। –

1

ऐसा लगता है कि आपको getline का उपयोग करने की आवश्यकता है, और उसके बाद पंक्ति का विश्लेषण करें। इसे पार्स करने के लिए एक समाधान लाइन को पहले अंक से ठीक पहले विभाजित करना होगा, फिर पहले छमाही को ट्रिम करें, और नाम के लिए इसका उपयोग करें, और दो नंबरों को पढ़ने के लिए std::istringstream का उपयोग करके दूसरे छमाही को पार्स करें। यह असफल हो जाएगा, बेशक, अगर किसी के पास उनके नाम के हिस्से के रूप में अंक है, लेकिन जो मुझे वैध सीमा मानता है। दूसरे शब्दों में, प्रत्येक पंक्ति के लिए , है न चाहते हैं:

std::string::iterator first_digit 
     = std::find_if(line.begin(), line.end(), IsDigit()); 
if (first_digit == line.end()) { 
    // format error... 
} else { 
    name = trim(std::string(line.begin(), first_digit)); 
    std::istringstream parser(std::string(first_digit, line.end())); 
    parser >> firstNumber >> secondNumber >> std::ws; 
    if (!parser || parser.get() != EOF) { 
     // format error... 
    } else { 
     // Do what ya gotta do. 
    } 
} 
1

कुछ इस तरह काम करना चाहिए:

std::string str; 
while(getline(infile, str)) 
{ 
    std::string::size_type pos; 
    pos = str.find_last_of(' '); 
    if (pos == std::string::npos || pos < 1) 
    { 
     cout << "Something not right with this string: " << str << endl; 
     exit(1); 
    } 
    int last_number = stoi(str.substr(pos)); 
    str = str.substr(0, pos-1); // Remove the number and the space. 
    pos = str.find_last_of(' '); 
    if (pos == std::string::npos || pos < 1) 
    { 
     cout << "Something not right with this string: " << str << endl; 
     exit(1); 
    } 
    int first_number = stoi(str.substr(pos)); 
    str = str.substr(0, pos-1); 
    // str now contains the "name" as one string. 

    // ... here you use last_number and first_number and str to do what you need to do. 
} 
0

मैं अपनी समस्या का समाधान को लागू किया है (ज्यादातर अपने ही सीखने के लिए)। यह इरादे के रूप में काम करता है, लेकिन यह थोड़ा लंबा लगता है।

#include<string> 
#include<fstream> 
#include<sstream> 
#include<iostream> 
#include<vector> 
#include<algorithm> 
#include<iterator> 

struct PlayerData { 
    std::string name; 
    int number; 
    int points; 
}; 

std::ostream& operator<<(std::ostream& os, const PlayerData& p) { 
    os<<"Name: "<<p.name<<", Number: "<<p.number<<", Points: "<<p.points; 
    return os; 
} 

PlayerData parse(const std::string& line) { 
    PlayerData data; 
    std::stringstream ss(line); 
    std::vector<std::string> tokens; 
    std::copy(std::istream_iterator<std::string>(ss), 
      std::istream_iterator<std::string>(), 
      std::back_inserter<std::vector<std::string>>(tokens)); 
    data.points = std::stoi(tokens.at(tokens.size() - 1)); 
    data.number = std::stoi(tokens.at(tokens.size() - 2)); 
    for(auto it=tokens.begin(); it!=tokens.end()-2; ++it) { 
    data.name.append(" "); 
    data.name.append(*it); 
    } 
    return data; 
} 

int main(int argc, char* argv[]) { 
    std::string line; 
    std::vector<PlayerData> players; 

    { // scope for fp          
    std::ifstream fp(argv[1], std::ios::in); 
    while(!fp.eof()) { 
     std::getline(fp, line); 
     if(line.size()>0) { 
     players.push_back(parse(line)); 
     } 
    } 
    } // end of scope for fp 

    // print list of players, or do whatever you want with it. 
    for(auto p:players) { 
    std::cout<<p<<std::endl;  
    } 

    return 0; 
} 

जी ++ समर्थन सी ++ 11 (मेरे मामले में जीसीसी 4.7.2) के संस्करण के साथ संकलित करें।

[Prompt] g++ -oparseline parseline.cpp -std=c++11 -O2 
[Prompt] ./parseline players.txt 
Name: Fernando Torres, Number: 9, Points: -29 
Name: Cristiano Ronaldo, Number: 7, Points: 31 
Name: Wayne Rooney, Number: 10, Points: 37 
Name: Neymar, Number: 17, Points: 29 
Name: Andres Iniesta, Number: 8, Points: 32 
Name: Robin van Persie, Number: 19, Points: 20 
Name: Lionel Messi, Number: 10, Points: 43 
Name: Xavi Hernandez, Number: 6, Points: 36 
Name: Mesut Özil, Number: 10, Points: 38 
Name: Didier Drogba, Number: 10, Points: 35 
Name: Fernando Torres, Number: 9, Points: 29 
Name: Kaká, Number: 10, Points: 17 
संबंधित मुद्दे