0

I Want to create console application which take command as input from user. Like

● On running app it should show a prompt

● On the prompt user can input following commands

○ exit : to exit

○ parse : parse given file

○ show last : show info of last parsed files

○ show : show info of all parsed files individually

○ del: delete info of oldest file parsed.

Parsing and other logic I know. i just want to how can i create console in application which take string as a command from user.

Thanks in advance.

YADAV
  • 115
  • 1
  • 11
  • Is what I answered close to what you are looking for? It was based mainly on my interpretation of your original question, but with more info I could provide you with some advice concerning how to perform the various tasks. – Lilith Daemon Jul 29 '15 at 03:50
  • Did anyone spot the irony in this sentence? *Parsing and other logic I know. i just want to how can i create console in application which take string as a command from user.* – paddy Jul 29 '15 at 06:43
  • @paddy That truly was humorous, He could use some work on clarifying exactly what he knows, and how much he needs to learn/wants answered. – Lilith Daemon Jul 29 '15 at 12:25

2 Answers2

1

Use std::cin and 'std::string' and just compare the user input to exit, parse and et cetera.

M. Shaw
  • 1,742
  • 11
  • 15
0

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>
Lilith Daemon
  • 1,473
  • 1
  • 19
  • 37