C++ parsing complicated file where each line specifies a command -
so need ideas on how nicely parse text file in c++. files parsing have following format :
command_a list of arguments command_b list of arguments etc etc
right using ifstream open file , have super long series of if-else statements determine each type of command. proving bit unwieldy (especially since of commands parsing other files...so have nested if-elses multiple ifstreams different files).
i looking way of doing not sure best approach. thinking using std::map keys command strings , values function pointers not familiar storing function pointers in map (especially if different functions of different return types, etc).
below doing. loop through file , use "getline" current line. use stringstream parse command. use long list of if-elses determine function call. each line in file comes list of arguments use stringstream parse , pass parameters function call.
the problem here two-fold
1) have very large number of if-elses (around 50)
2) of commands require me parse new files , have open ifstream within current ifstream. (see command_c)
so i'm looking easier/more efficient/prettier looking way this.
/*open file , verify validity*/ std::ifstream parsefile(filename.c_str()); if(!parsefile.good()) { cerr<<"error: file either corrupt or not exist."<<endl; exit(1); //terminate program } //loop on file line line std::string line; while(!parsefile.eof()) { std::getline(parsefile, line); std::stringstream ss; std::string command; ss.str(line); ss >> command; if(command == "command_a") { float x,y,z; ss >> x >> y >> z; functiona(x,y,z); } else if(command == "command_b") { float a,b,c,d,e,f; ss >> >> b >> c >> d >> e >> f; functionb(a,b,c,d,e,f); } else if(command == "command_c") { string nextfile; ss >> nextfile; parsefile(nextfile); //this not recursive...this function } else if(...) { ... } // etc, etc (this continues on long time) } parsefile.close();
you have command map , register bunch of functions:
#include<fstream> #include<functional> #include<iostream> #include<map> #include<sstream> int main() { typedef std::function<bool (std::istringstream&)> command_function; typedef std::map<std::string, command_function> command_map; command_map map; // register commands map.insert(command_map::value_type("print", [](std::istringstream& s) { std::string line; if( ! getline(s, line)) return false; std::cout << line << '\n'; return true; })); map.insert(command_map::value_type("add", [](std::istringstream& s) { double a; double b; if( ! (s >> >> b)) return false; std::cout << "a + b = " << + b << '\n'; return true; })); // sample data std::istringstream file( "print hello world\n" "add 1 2\n"); // command parsing std::string line; while(getline(file, line)) { std::istringstream line_stream(line); std::string command; if(line_stream >> command >> std::ws) { auto pos = map.find(command); if(pos != map.end()) pos->second(line_stream); } } return 0; }
Comments
Post a Comment