想要创建打开控制台的应用程序并将用户输入作为命令

时间:2015-07-29 03:11:18

标签: c++ console-application

我想创建控制台应用程序,它将命令作为用户的输入。  像

●在运行应用时,它应显示提示

●在提示中,用户可以输入以下命令

○退出:退出

○解析:解析给定文件

○show last:显示最后解析文件的信息

○show:单独显示所有已解析文件的信息

○del:删除已解析的最旧文件的信息。

我知道解析和其他逻辑。我只想知道如何在应用程序中创建控制台,将字符串作为用户的命令。

提前致谢。

2 个答案:

答案 0 :(得分:1)

使用std::cin和' std :: string'并且只是将用户输入与exitparse等进行比较。

答案 1 :(得分:0)

注意:这主要是基于我对OP原始问题的解释。它现在还没有完全回答这个问题,但如果其他任何人都能从中受益,我会把它作为答案。

您可以从创建一个我们将调用CommandBase的类开始。为了演示的目的,我将使用字符串和向量。

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";
    }

};

为了这个例子的目的,我们将实现一个退出程序的函数和一个将输入数字加倍的函数。

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;

现在我们已经完成了CommandExit,我们需要调用我们的函数。让我们自己成为一个函数foo,它将从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);
        }
    }
}

现在要测试我们将首先提供无效命令的参数:

  

invalidCommand1 invalidParam1

我们收到了输出:

  

我们将执行命令:invalidCommand1

     

我们将使用参数:invalidParam1

     

命令:invalidCommand1未重新配置。请再试一次。

现在让我们测试程序是否会正确加倍。我们将提供输入:

  

双5

我们收到了输出:

  

我们将执行命令:double

     

我们将使用参数:5

     

双倍:5是10

最后,我们使用输入

检查退出案例
  

出口

我们收到了输出:

  

我们将执行命令:exit

     

我们将使用参数:

     

退出

程序成功终止。

我们可以看到所有选项都正确执行,您可以轻松定义新命令并处理所提供的参数,但是您可以选择。 我希望这有帮助。

让我们说你想创建更多需要多个参数的高级命令。首先,我们需要创建一个函数来将参数拆分为“行”。

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;
}

现在我们可以有效地分割代码,让我们实现两个新功能。一个用于将给定数字提升到给定功率,另一个用于将消息写入文件。

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;

这两个功能都可以通过以下方式进行测试:

输入:

  

pow 10 2

输出:

  提升到10的力量:2是100

对于fileWrite,我们可以检查:

  

写out.txt这是一条消息。

当我们查看生成的out.txt文件时,它包含:

  

这是一条消息。

再一次,我希望这会有所帮助。

编辑:

我没有关于输入是否正确的错误检查,因此您可能希望在需要时添加它。 (例如,CommandDouble不检查参数是否实际为数字)无论如何,如果您有任何问题;随便问。

编辑2:

我刚看到你在开始研究之后对你的问题进行了更新。您必须为您的文件解析实现CommandBase的子项(取决于您要如何解析它。)您应该能够使用此框架或类似的框架来创建Parse命令。至于创建帮助,您可以执行以下操作:

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;
}

当用户输入错误的命令和程序开始时,您可以调用此方法。

编辑3:

更新了一些代码,并添加了一些函数来演示如何解析参数。我还调整了帮助功能,以读取每个命令的帮助文本,并将其调用合并到foo中。完整的源代码可在以下位置找到:http://pastebin.com/y0KpAu5q

编辑4:

对于那些可能有帮助的人,代码中使用的包括:

#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <fstream>