Note: This was mostly based off my interpretation of the OP's original question. It doesn't fully answer the question as of now, however I will leave it as an answer should anyone else manage to benefit from it.
You could start by creating a class that we will call CommandBase. I will be using string and vector for the purposes of this demonstration.
class CommandBase{
protected:
std::string m_name;//The internal name
std::string m_help;//The internal help line
public:
//The public interface for name.
const std::string &name = m_name;
//The public interface for the help line.
const std::string &help = m_help;
virtual void execute(const std::string &line){}
CommandBase(){
m_name = "BASE_COMMAND";
m_help = "BASE_HELP_MESSAGE";
}
};
And for the purposes of this example, we will implement a function that exits the program and a function that will double an inputted number.
class CommandExit : public CommandBase{
public:
CommandExit(){
m_name = "exit";
m_help = "exit ~ Will cause the program to terminate. ";
}
virtual void execute(const std::string &line){
std::cout<<"Exiting"<<std::endl;
exit(0);
}
}commandExit;
class CommandDouble : public CommandBase{
public:
CommandDouble(){
m_name = "double";
m_help = "double <number1> ~ Will output number1 times two. ";
}
virtual void execute(const std::string &line){
int i = std::atoi(line.c_str());
std::cout<<"The double of: "<<i<<" is "<<i*2<<std::endl;
}
}commandDouble;
Now that we have the CommandExit completed, we need to call our functions. Lets make ourselves a function foo that will read the command and the parameters from std::cin.
void foo(){
std::vector<CommandBase*> commandList;
commandList.push_back(&commandExit);
commandList.push_back(&commandDouble);
commandList.push_back(&commandPower);
commandList.push_back(&commandFileWrite);
std::string ourCommand;
std::string ourParameters;
help(commandList);
while(true){
std::cin>>ourCommand;
std::getline(std::cin,ourParameters);
//Remove any preceeding whitespace.
ourParameters.erase(ourParameters.begin(), std::find_if(ourParameters.begin(), ourParameters.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
std::cout<<"We will execute the command: "<<ourCommand<<std::endl;
std::cout<<"We will use the parameters: "<<ourParameters<<std::endl;
bool foundCommand = false;
for(unsigned i = 0; i < commandList.size(); ++i){
if(commandList[i]->name == ourCommand){
foundCommand = true;
commandList[i]->execute(ourParameters);
break;
}else continue;
}
if(!foundCommand){
std::cout<<"The command: "<<ourCommand<<" was not reconized. Please try again."<<std::endl;
help(commandList);
}
}
}
Now to test we will supply first the argument of an invalid command:
invalidCommand1 invalidParam1
We receive the output:
We will execute the command: invalidCommand1
We will use the parameters: invalidParam1
The command: invalidCommand1 was not reconized. Please try again.
Now lets test if the program will double correctly. We will provide the input:
double 5
and we receive the output:
We will execute the command: double
We will use the parameters: 5
The double of: 5 is 10
Finally we check the exit case with the input:
exit
And we receive the output:
We will execute the command: exit
We will use the parameters:
Exiting
And the program successfully terminates.
As we can see all the options are executing correctly, and you can easily define new commands and process the provided parameter however you choose.
I hope this helps.
Lets say however you want to create more advanced commands that require multiple parameters. First we need to create a function to split the parameters in "line" up.
int split(const std::string& line, const std::string& seperator, std::vector<std::string> * values){
std::string tString = "";
unsigned counter = 0;
for(unsigned l = 0; l < line.size(); ++l){
for(unsigned i = 0; i < seperator.size(); ++i){
if(line[l+i]==seperator[i]){
if(i==seperator.size()-1){
values->push_back(tString);
tString = "";
++counter;
}else continue;
}else{
tString.push_back(line[l]);
break;
}
}
}
if(tString!="")values->push_back(tString);
return counter;
}
Now that we can effectively split the code, let us implement two new functions. One to raise a given number to a given power, and another to write a message to a file.
class CommandPower : public CommandBase{
public:
CommandPower(){
m_name = "pow";
m_help = "pow <number1> <number2> ~ Will raise number 1 to the power of number 2. ";
}
virtual void execute(const std::string &line){
double d, exp;
std::cout<<"Param:"<<line<<std::endl;
std::vector<std::string> vals;
split(line," ",&vals);
assert(vals.size()>=2);//We don't want a nasty Out Of Bounds.
for(unsigned i = 0; i < vals.size(); ++i){
std::cout<<"Vals["<<i<<"] = "<<vals[i]<<std::endl;
}
d = std::atof(vals[0].c_str());
exp = std::atof(vals[1].c_str());
std::cout<<d<<" raised to the power of: "<<exp<<" is "<<pow(d,exp)<<std::endl;
}
}commandPower;
class CommandFileWrite : public CommandBase{
public:
CommandFileWrite(){
m_name = "write";
m_help = "write <filename> [message] ~ Will append the message to the specified file. ";
}
virtual void execute(const std::string &line){
std::cout<<"Param:"<<line<<std::endl;
std::vector<std::string> vals;
split(line," ",&vals);
assert(vals.size()>=1);//We don't want a nasty Out Of Bounds.
for(unsigned i = 0; i < vals.size(); ++i){
std::cout<<"Vals["<<i<<"] = "<<vals[i]<<std::endl;
}
//The stream for the file we will save.
std::ofstream fts;
fts.open(vals[0].c_str(), std::ios::out|std::ios::app);
if(fts.is_open()){
for(unsigned i = 1; i < vals.size(); ++i){
if(i+1<vals.size()) fts<<vals[i]<<" ";
else fts<<vals[i]<<std::endl;
}
}else{
std::cerr<<"Cannot open the file: "<<vals[0]<<std::endl;
return;
}
}
}commandFileWrite;
Both of these functions can be tested by looking at:
input:
pow 10 2
output:
10 raised to the power of: 2 is 100
And for the fileWrite we can check:
write out.txt This is a message.
Which when we look at the generated out.txt file, it contains:
This is a message.
Once again, I hope this helps.
EDIT:
I don't have any error checking regarding that inputs will be correct, so you will likely want to add that if needed. (E.G. the CommandDouble doesn't check if the parameters are actually numbers) Anyhow, if you have any questions; feel free to ask.
EDIT 2:
I just saw you made an update to your question after I had started working on this. You would have to implement a child of CommandBase for your file parsing (depending on how you want to parse it.) You should be able to use this framework or a similar one for creating your Parse Command. As for creating help, you can do something like below:
void help(){
std::cout<<"---------------Operating Instructions---------------"<<std::endl
<<"Use double <number> to double an inputted number "<<std::endl
<<"Use exit to close the program "<<std::endl;
}
You could possibly call this when the user enters an incorrect command and when the program begins.
EDIT 3:
Updated some of the code, and added a few more functions to demonstrate how you could go about parsing the parameters. Also I adjusted the help function to read each command's help text, and incorporated it's calling into foo. The complete source code can be found at: http://pastebin.com/y0KpAu5q
EDIT 4:
For those this may help, the includes used in the code are:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <fstream>