operator()でCSVパーサ
boost::program_optionsの
operator()の使い方に触発されて、
CSVパーサを実装。
#include <fstream> #include <boost/tokenizer.hpp> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> typedef boost::char_separator<char> separator; typedef boost::tokenizer<separator> tokenizer; // CSVパーサクラス class CsvParser { std::ifstream m_ifs; const string m_file; tokenizer::const_iterator m_tok; tokenizer::const_iterator m_tokEnd; public: CsvParser(const string& file) : m_file(file), m_ifs() { m_ifs.open(file); } ~CsvParser(void) { m_ifs.close(); } // 次の行へ bool next(void) { bool readStat; if (!m_ifs) { return false; } std::string line; try { readStat = (bool) getline(m_ifs, line); if (readStat) { tokenizer tokens(line, separator(",")); m_tok = tokens.begin(); m_tokEnd = tokens.end(); } } catch (std::exception &ex) { readStat = false; } return readStat; } // ()の連結で、各要素を取得 template<typename T> CsvParser& operator() (T* v) { if (m_tok == m_tokEnd) { throw std::exception("no more token in this line."); } try { *v = boost::lexical_cast<T>(boost::trim_copy(*m_tok)); ++m_tok; } catch (std::exception &ex) { std::cerr << ex.what() << std::endl; v = NULL; } return *this; } }; //実行 int main(int argc, char** argv) { CsvParser csv("input.csv"); int id; string name; double val; while ( csv.next() ) { csv(&id)(&name)(&val); cout << "ID:"<< id << ",Name:" << name << ",Value:" << val << endl; } return 0; }
この実装なら、operator>>を使ったほうが素直かしら。