2013-06-20 2 views
0

Привет всем Я не новичок в C++, но мои навыки не очень отточены. В любом случае у меня есть задание, которое я не смог выполнить вовремя, и это действительно подслушивает меня, что я не мог заставить свой код работать. Теперь я просто хочу закончить его, чтобы я мог знать, как это сделать в будущем.C++ Чтение столбцов файла .txt в массив

Файл данных содержит количество игроков и их баллы в одной строке, а последним столбцом является их время.

Вопрос в том, что есть файл .txt, который должен открыть в моей программе, который читается как это (без маркеров).

  • поп 23 45 92 34 43 125
  • КС 4 23 56 23 75 323
  • ... и так далее.

Как я могу хранить/игнорировать первую переменную, а затем создавать массивы с столбцом данных по столбцу (отделяется пробелом)?

Вот что я создал. Я создал массивы, которые мне нужны для хранения соответствующих данных.

#include <iostream> 
#include <cmath> 
#include <ctime> 
#include <iomanip> 
#include <vector> 
#include <string> 
#include <sstream> 
#include <fstream> 
using namespace std; 

int main() 
{ 
    cout<<"Welcome to the Score Sorting Program! \n"; 
    cout<<"Please choose a number that corresponds with the way you would like to sort. \n"; 
    cout<<"You may also search by player if you know their username. \n"; 

    string players[50]; //Allocated space for 50 players. 
    int score1[27]; //Array for Score 1 
    int score2[27]; // 
    int score3[27]; // 
    int score4[27]; // 
    int score5[27]; // 
    int time[27]; //Array for Time 
    int i = 0; 
    int j = 0; 

    ifstream myfile; 
    myfile.open("G2347M.txt"); 
    if (!myfile) 
    { 
     cout<<"Could not open file. \n"; 
     system ("Pause"); 
     return -1; 
    } 

    while (!myfile.eof()) 
    { 
     getline(myfile, players[i], ' '); 
     if (i == 26) 
     { 
      i=0; 
      ++j; 
      getline(myfile, players[i],' '); 
     } 
     i++; 
    }  

} 

Таким образом, в основном я выровняю игроков с их результатами и выдаст их в другой файл. Я просто хочу получить эту первую часть чтения файла, а затем я перейду.

Я исследовал похожие темы (4 часа +), пытаясь собрать вместе код, чтобы заставить мое работать. Я продолжу исследовать и обновлять все, что смогу.

+0

Я нашел несколько потоков о сохранении первого числа с помощью вектора, но мне нужно было использовать массивы. –

+1

Почему игроки массируют массив ints? Похоже, что это будет массив строк для имен игроков. –

+0

К сожалению, просто изменил его на строки. –

ответ

0

Вот такой подход, который использует инкапсуляцию и перегрузку оператора >>. Я предполагаю, что то, что вы описывали для ввода, было просто длинной последовательностью пространственных разделенных входных значений, при этом первым значением было количество игроков.

#include <iostream> 
#include <iomanip> 
#include <string> 
#include <sstream> 
#include <fstream> 
#include <ctype.h> 

using namespace std; 

static const size_t MaxNumPlayers = 50; 

// C++ is about encapsulation, and the player data is 
// discrete yet related, so encapsulate it. 
struct Player 
{ 
    string m_name; 
    int m_scores[5]; 
    size_t GetNumScores() const { return sizeof(m_scores)/sizeof(m_scores[0]); } 
    int m_time; 
}; 

// This allows us to write an operator that will read a player 
// directly from an ifstream. 
std::ifstream& operator>>(ifstream& istr, Player& player) 
{ 
    istr >> player.m_name; 
    for(size_t i = 0; i < player.GetNumScores(); ++i) 
    { 
     istr >> player.m_scores[i]; 
    } 
    istr >> player.m_time; 
    cout << "player: " << player.m_name << ", " << player.m_scores[0] << " @ " << player.m_time << endl; 
    return istr; 
} 

int main(int argc, const char** argv) 
{ 
    ifstream myfile("G2347M.txt"); 
    if (!myfile) 
    { 
     cout<<"Could not open file. \n"; 
     system("Pause"); 
     return -1; 
    } 

    // We can read the number of players directly. 
    size_t numPlayers = 0; 
    myfile >> numPlayers; 
    if (numPlayers <= 0 || numPlayers > MaxNumPlayers) { 
     cout << "Invalid number of players in score file ("<<numPlayers<<")." << endl; 
     system("Pause"); 
     return -1; 
    } 

    Player players[MaxNumPlayers]; 
    size_t playersRead = 0; 

    while (!myfile.eof()) 
    { 
     myfile >> players[playersRead++]; 
     if (playersRead >= numPlayers) 
      break; 
     // drain any spaces after the player. 
     while(isspace(myfile.peek())) 
      myfile.ignore(); 
    } 

    if (playersRead != numPlayers) 
    { 
     cout << "Problem reading score file, expected " << numPlayers << " but read " << playersRead << endl; 
     system("Pause"); 
     return -1; 
    } 

    cout<<"Welcome to the Score Sorting Program! I read "<<playersRead<<" players."<<endl; 
    cout<<"Please choose a number that corresponds with the way you would like to sort."<<endl; 
    cout<<"You may also search by player if you know their username.\n"<<endl; 

    /* ... */ 

    system("Pause"); 
    return 0; 
} 
+0

Можете ли вы объяснить использование size_t при объявлении MaxNumPlayers вверху? Я немного смущен тем, что именно происходит там, но я вижу, что это снова используется в основной функции, где она читает 'if (numPlayers <= 0 || numPlayers> MaxNumPlayers) {...}' – andrewec

+0

' size_t' является относительно стандартным типом для хранения значений размера. 'static const size_t NumPlayers = 5;' - константа локально скопированной, иными словами, вместо использования '5' везде, я создал значимое именованное значение. Если вы видите 'int x = 32 + 5;' или 'int x = 37;' как вы можете определить, что такое эти числа? 'int x = FirstPlayerNum + NumPlayers' сам объясняет. – kfsone

+0

Это имеет смысл - но почему бы просто не использовать 'static const NumPlayers = 5'? Я думаю, именно там меня повесили трубку. – andrewec

0

Почему 50 игроков, но только 27 баллов?

Предполагаю, что первая строка - это общее количество строк, которые вы ожидаете прочитать? Если это так, вы можете динамически распределять массивы для хранения всех данных, а не только для обработки 50 (или это 27) строк. Вы могли бы также объединить все данные для одной строки в структуру вместо того, чтобы распространять ее на связку отключенных массивов.

псевдокод:

int lineNo = 1; 
int totalLines = -1; /* not set */ 

while(line = read_a_line()) { 
    if (lineNo == 1) { 
     totalLines = convert_line_text_to_number(); 
    } 
    else { 
     /* split the line into "tokens" separated by white space */ 
     /* store each token in the correct array */ 
    } 
    lineNo++; 
    /* if lineNo is too big, break the loop */ 
} 
+0

Это 27 строк, но в инструкциях сказано выделить место для до 50 игроков. В файле есть 27. –

0

Лучший способ использовать это будет использование векторов. но, как вы сказали, что вы обязаны использовать массивы, вот вот код для этого.

#include <iostream> 
#include <fstream> 
#include <sstream> 

using namespace std; 

int main() 
{ 
    ifstream file; 
    file.open("sample.txt"); 

    string name[50]; 
    int score1[27],score2[27],score3[27],score4[27],score5[27],time[27]; 


    int i = 0; 
    while(!file.eof()) 
    { 
     string line; 
     getline(file,line); 
     char* a = const_cast<char*>(line.c_str()); 
     char* pch = strtok (a," "); 

     name[i] = pch; 
     int counter = 1; 
     while (counter < 7) 
     { 
      pch = strtok (NULL, " "); 

      if(counter == 1) 
      { 
       score1[i] = atoi(pch); 
      } 
      else if(counter == 2) 
      { 
       score2[i] = atoi(pch); 
      } 
      else if(counter == 3) 
      { 
       score3[i] = atoi(pch); 
      } 
      else if(counter == 4) 
      { 
       score4[i] = atoi(pch); 
      } 
      else if(counter == 5) 
      { 
       score5[i] = atoi(pch); 
      } 
      else if(counter == 6) 
      { 
       time[i] = atoi(pch); 
      } 

      ++counter; 
     } 

     ++i; 
    } 

    //cout<<a; 
    return 0; 
} 

Пожалуйста, дайте мне знать, если у вас возникнут какие-либо проблемы. Я не добавил некоторые основные проверки здравомыслия, например, файлы, пожалуйста, сделайте это в своей версии.

Смежные вопросы