2013-07-17 3 views
0

Я пытаюсь отобразить данные текстового файла в столбцы, используя структуру класса и функцию getline() для чтения текстового файла и дампа данных в векторный класс. Но похоже, что программа даже не запустилась в мой цикл while, а затем покинула программу. Текстовый файл не пуст.getline не работает как ожидалось

Ниже мой код:

void ScrambleWordGame::displayScoreChart() { 
//open file 
fstream readScoreChart("ScoreChart.txt"); 
string line = ""; 

//vector to store data in 
vector<personResult> perResult; 
personResult person; 

//while file is open, do stuff 
if(readScoreChart.is_open()) 
{ 
    //check through the file 
    readScoreChart.seekp(0,ios::end); 
    //get the size of the file's data 
    size_t size = readScoreChart.tellg(); 
    if(size == 0) 
     cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl; 
    else 
    { 
     //create the 1st row with 4 column names 
     cout << left 
      << setw(20) << "Player Name " 
      << setw(20) << "Winning Time " 
      << setw(20) << "No. Of Attempts " 
      << setw(20) << "Game Level " << endl; 
     //fill the second line with dashes(create underline) 
     cout << setw(70) << setfill('-') << "-" << endl; 
     //read the file line by line 
     //push the 1st line data into 'line' 
     cout << getline(readScoreChart,line); 
     while(getline(readScoreChart,line)) 
     { 
      //create stringstream n push in the entire line in 
      stringstream lineStream(line); 

      //reads the stringstream and dump the data seperated by delimiter 
      getline(lineStream,person.playerName,':'); 
      getline(lineStream,person.winningTime,':'); 
      getline(lineStream,person.noOfAttempts,':'); 
      getline(lineStream,person.gameLvl); 

      //sort the results based on their timing 
      //sort(perResult.begin(),perResult.end(),pRes); 
      //display the results 
      cout << left 
        << setfill(' ') 
        << setw(25) << person.playerName 
        << setw(22) << person.winningTime 
        << setw(17) << person.noOfAttempts 
        << setw(16) << person.gameLvl 
        << endl; 
     } 
    } 
} 
readScoreChart.close(); 

}

Edit: Пример Textfile
Иоиля: 3: 1: 1
Марии: 5: 2: 2
John: 25 : 3: 1

+1

Не могли бы вы разместить пару строк текстового файла, который вы пытаетесь разобрать, пожалуйста? – jrd1

+1

'readScoreChart.seekp (0, ios :: end);' - файл может быть пустым, но вы пропускаете все содержимое. – Casey

+0

@Casey Я делаю это, чтобы проверить, пустой ли текстовый файл или нет. После проверки указатель должен вернуться наверх, не так ли? –

ответ

2

Ваш указатель файла находится в конце файла после вашего первого поиска. Вам нужно переместить его в начало файла.

if(size == 0) 
{ 
    cout << "No results yet. Please TRY to win a game. AT LEAST~" << endl; 
} 
else 
{ 
    readScoreChart.seekp(0,ios::begin); 
    // all you other stuff 
} 
+0

Теперь я могу отображать данные из текстового файла. Но теперь этот «0x7fff52b710e0Mary» выходит на моем выходе. Кто-нибудь знает, что в этом плохого? –

+0

Решает проблему, но я предпочел бы разместить этот второй 'seekp' сразу после' tellg' (перед тестированием 'size') –

+0

@gx Я стараюсь совершать звонки в том месте, где они мне нужны (i) ради эффективность и (ii) ради упрощения обслуживания – ogni42

1

Чтобы читать, вам нужно искать назад к началу файла. Еще лучше, просто не пытайтесь до конца в первую очередь.

Я бы немного переструктурировал код - напишите operator>>, чтобы прочитать запись из файла, и operator<<, чтобы записать запись в файл.

class person { 
    std::string name; 
    std::string winning_time; 
    std::string num_attempts; 
    std::string level; 

public: 
    bool operator<(person const &other) const { 
     return std::stoi(winning_time) < std::stoi(other.winning_time); 
    } 

    friend std::istream &operator>>(std::istream &in, person &p) { 
      std::string buffer; 
      std::getline(in, buffer); 
      std::istringstream is(buffer); 

      std::getline(is,p.name,':'); 
      std::getline(is,p.winning_time,':'); 
      std::getline(is,p.num_attempts,':'); 
      std::getline(is,p.level); 
      return in; 
    } 

    friend std::ostream &operator<<(std::ostream &os, person const &p) { 
      return os << std::setw(25) << p.name 
         << std::setw(22) << p.winning_time 
         << std::setw(17) << p.num_attempts 
         << std::setw(16) << p.level; 
    } 

}; 

С тех на месте, остальное получает совсем немного проще:

void show_header(std::ostream &os) { 
    cout << left 
     << setw(20) << "Player Name " 
     << setw(20) << "Winning Time " 
     << setw(20) << "No. Of Attempts " 
     << setw(20) << "Game Level " << "\n"; 
    std::cout << std::string(70, '-'); 
} 

void game::displayScoreChart(){ 
    std::ifstream in("ScoreChart.txt"); 

    // read the data: 
    std::vector<person> people{std::istream_iterator<person>(in), 
           std::istream_iterator<person>()}; 

    if (people.empty()) { 
     std::cout << "No scores yet." 
     return; 
    } 

    // sort it by winning time: 
    std::sort(people.begin(), people.end()); 

    show_header(std::cout); 

    // display it: 
    for (auto const &p : people) 
     std::cout << p << "\n"; 
    return 0; 
} 

В качестве простой замены, если у вас нет C++ 11 компилятора, stoi может быть написано что-то например:

int stoi(std::string in) { 
    return strtol(in.c_str(), NULL, 10); 
} 
+0

Что стоит stoi? –

+0

@JoelSeah: "string to integer". Добавлено в C++ 11 (но в C++ 03 есть приблизительные эквиваленты). –

+0

Мне нужно включить это в заголовок? –