2013-06-16 2 views
0

Я использовал следующий фрагмент кода для чтения из нескольких файлов .dat и проанализировал их. Этот код использует 3D-векторы для хранения данных после процесса чтения. Однако я хотел бы, чтобы данные, соответствующие каждому отдельному файлу, были независимы от других. Проблема в том, что количество файлов меняется и неизвестно во время компиляции; следовательно, число векторов тоже меняется. Я хотел бы знать, есть ли какое-либо решение для этого.Хранение данных из неизвестного количества файлов

vector<vector<vector<string>>> masterList; 

for (int i = 0; i < files.size(); ++i) { 
    cout << "file name: " << files[i] << endl; 

    fin.open(files[i].c_str()); 
    if (!fin.is_open()) { 
     // error occurs!! 
     // break or exit according to your needs 
     cout<<"error"<<endl; 
    } 

    std::vector<vector<string>> tokens; 

    int current_line = 0; 
    std::string line; 
    while (std::getline(fin, line)) 
    { 

     cout<<"line number: "<<current_line<<endl; 
     // Create an empty vector for this line 
     tokens.push_back(vector<string>()); 

     //copy line into is 
     std::istringstream is(line); 
     std::string token; 
     int n = 0; 

     //parsing 
     while (getline(is, token, DELIMITER)) 
     { 
      tokens[current_line].push_back(token); 
      cout<<"token["<<current_line<<"]["<<n<<"] = " << token <<endl; 

      n++; 
     } 
     cout<<"\n"; 
     current_line++; 
    } 
    fin.clear(); 
    fin.close(); 
    masterList.push_back(tokens); 
} 

Итак, главный вопрос, я столкнулся: как создать переменное число 2D векторов для хранения данных, соответствующих каждому отдельному файлу, когда я не знаю, сколько файлов есть во время компиляции время.

+2

3D-вектор содержит переменное число двумерных векторов. Поскольку у вас уже есть 3D-вектор, я не уверен, что вы спрашиваете. – interjay

+0

Err, я полностью потерял вас, ЧТО это проблема с опубликованным кодом? Кажется, это точно то, что вы описываете по мере необходимости. –

+0

@interjay Проблема состоит в том, чтобы хранить каждый файл в отдельный вектор, поэтому я могу использовать эти векторы по отдельности позже. – Hawk

ответ

1

Измените список файлов в главном, чтобы настроить размер ваших «основных данных». Если длина имен файлов является переменной, сначала проанализируйте ее (или сначала получите ее), а затем выполните синтаксический анализ файлов dat. Если имена файлов известны только во время выполнения и асинхронно с этим, добавьте новый элемент в список каждый раз, когда вы получите новое имя файла (например, вы можете использовать события для этого, посмотрите на https://github.com/Sheljohn/siglot).

Обратите внимание, что элементы списка независимы в памяти, и это указывает на удаление/вставку поддержки в постоянное время. Таким образом, данные, соответствующие каждому файлу, не зависят друг от друга. Если вы хотите получить данные, специфичные для файла (зная имя файла), либо итерации в списке, чтобы найти соответствующий файл (линейное время), либо обменять список на unordered_map (амортизированное постоянное время).

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

using namespace std; 

#define AVG_LINES_PER_FILE 100 



/** 
* [tokenize_string Tokenize input string 'words' and put elements in vector 'tokens'.] 
* @param words [Space separated data-string.] 
* @param tokens [Vector of strings.] 
*/ 
void tokenize_string(string& words, vector<string>& tokens) 
{ 
    unsigned n = count(words.begin(), words.end(), ' '); 
    tokens.reserve(n); 

    istringstream iss(words); 
    copy( 
     istream_iterator<string>(iss), 
     istream_iterator<string>(), 
     back_inserter<vector<string> >(tokens) 
    ); 
} 



/** 
* Contains data parsed from a single .dat file 
*/ 
class DATFileData 
{ 
public: 

    typedef vector<string> line_type; 
    typedef vector<line_type> data_type; 

    DATFileData(const char* fname = nullptr) 
     { 
      m_fdata.reserve(AVG_LINES_PER_FILE); 
      m_fdata.clear(); 

      if (fname) parse_file(fname); 
     } 

    // Check if the object contains data 
    inline operator bool() const { return m_fdata.size(); } 

    // Parse file 
    bool parse_file(const char* fname) 
     { 
      string line; 
      m_fdata.clear(); 
      ifstream fin(fname); 

      if (fin.is_open()) 
      { 
       while (fin.good()) 
       { 
        getline(fin,line); 
        m_fdata.push_back(line_type()); 
        tokenize_string(line, m_fdata.back()); 
       } 
       fin.close(); 

       m_fname = fname; 
       cout << "Parsed " << m_fdata.size() << " lines in file '" << fname << "'." << endl; 
       return true; 

      } 
      else 
      { 
       cerr << "Could not parse file '" << fname << "'!" << endl; 
       return false; 
      } 
     } 

    // Get data 
    inline unsigned size() const { return m_fdata.size(); } 
    inline const char* filename() const { return m_fname.empty() ? nullptr : m_fname.c_str(); } 
    inline const data_type& data() const { return m_fdata; } 
    inline const line_type& line(const unsigned& i) const { return m_fdata.at(i); } 

private: 

    string m_fname; 
    data_type m_fdata; 
}; 



int main() 
{ 

    unsigned fcount = 0; 
    vector<string> files = {"some/file/path.dat","another/one.dat"}; 
    list<DATFileData> data(files.size()); 

    for (DATFileData& d: data) 
     d.parse_file(files[fcount++].c_str()); 

    cout << endl << files.size() << " files parsed successfully." << endl; 
}