我想创建控制台应用程序,它将命令作为用户的输入。 像
●在运行应用时,它应显示提示
●在提示中,用户可以输入以下命令
○退出:退出
○解析:解析给定文件
○show last:显示最后解析文件的信息
○show:单独显示所有已解析文件的信息
○del:删除已解析的最旧文件的信息。
我知道解析和其他逻辑。我只想知道如何在应用程序中创建控制台,将字符串作为用户的命令。
提前致谢。
答案 0 :(得分:1)
使用std::cin
和' std :: string'并且只是将用户输入与exit
,parse
等进行比较。
答案 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>