regex 具有自定义用户输入指令和变量参数的交互式命令行应用程序

7vux5j2d  于 2023-08-08  发布在  其他
关注(0)|答案(1)|浏览(67)

我正在开发一个接收特定用户指令的命令行应用程序。我的解决方案是创建一个CommandTable类,用于处理命令(以类似regex的字符串形式)及其处理程序函数的所有匹配。
到目前为止,类看起来像这样:

#include <string>

class CommandTable
{
public:
  struct CommandStruct
  {
    std::string command;
    int (*commandHandler)();
  };

  CommandTable(int tableSize);
  int handleCommand(const std::string &command);
  int setCommand(int index, const std::string &command, int (*handler)());

private:
  CommandStruct *table;
  int tableSize;
  void commandNotFound();
};

字符串
及其实施:

#include "CommandTable.h"
#include <iostream>

CommandTable::CommandTable(int tableSize) : tableSize(tableSize)
{
  table = new CommandStruct[tableSize];
}

int CommandTable::handleCommand(const std::string &command)
{
  for (int i = 0; i < tableSize; ++i)
  {
    if (std::regex_match(command, std::regex(table[i].command)))
    {
      table[i].commandHandler();
      return 0;
    }
  }
  commandNotFound();
  return -1;
}

int CommandTable::setCommand(int index, const std::string &command, int (*handler)())
{
  if (index > tableSize - 1 || index < 0)
  {
    std::cerr << "Invalid index for command table: " << index << std::endl;
    exit(-1);
  }
  table[index].command = command;
  table[index].commandHandler = handler;
  return 0;
}

void CommandTable::commandNotFound()
{
  std::cout << "Command not found" << std::endl;
}


我创建每个可能的命令的方式如下:

#define COMMAND_TABLE_SIZE 3

int main()
{
  CommandTable commandTable = CommandTable(COMMAND_TABLE_SIZE);
  commandTable.setCommand(0, "initialize", initialize);
  commandTable.setCommand(3, "initialize (.+)", initializeFromFile);

  string inputCommand;
  cout << "cli> ";
  cin >> inputCommand;

  do
  {
    commandTable.handleCommand(inputCommand);
    cout << "cli> ";
    cin >> inputCommand;
  } while (inputCommand != "exit");

  return 0;
}


问题:
考虑这两个可能的指令:
1.初始化
1.初始化文件名
并且许多其他指令可以具有或不具有具有“自变量”或参数的第二形式,诸如“保存”。
目前,第一个应该只打印“Initializing...”,第二个应该打印相同的内容以及给定的文件名。为此,我创建了两个不同的函数来实现这一目的。第二个函数接收文件名作为参数来打印它。

int initialize()
{
  cout << "Initializing..." << endl;
  return 0;
}

int initializeFromFile(string filename)
{
  cout << "Initializing from: " << filename << endl;
  return 0;
}


问题是,当定义CommandStruct时,它接受一个没有参数的函数,所以我可以用initialize处理程序调用setCommand函数,但是添加一个带参数的函数,initializeFromFile我得到以下错误:
第一个月
反过来,通过在CommandStruct处理程序的定义中定义参数,现在第一个处理程序给出了相同的错误。
即使我能够毫无问题地定义这些处理程序,现在的问题是,我如何在handleCommand函数中正确地调用它们:

  • 如何从输入中提取参数?
  • 我如何调用函数取决于它是否有参数?
  • regex是定义命令的正确方法吗?
  • 是否是处理此类命令的好方法?

我尝试定义了很多方法来使用setCommand函数,这样我就可以添加带参数或不带参数的处理程序,但这会产生一些冲突,并且每次都会调用随机处理程序。

wr98u20j

wr98u20j1#

有很多可能的方法来做这件事。一个简单的解决方案是将cmd结构体更改为:

struct CommandStruct
{
  std::string name;
  std::function<int(std::vector<std::string>)> handler;
};

字符串
然后你可以从用户split it读取一行,用空格作为分隔符,然后用args调用它:

auto agrs = split(line, ' ');
int ret = table[i].commandHandler(args);


如果您希望始终将cmd名称作为第一个参数,或者在命令没有任何可选参数的情况下传递空参数列表,则由您决定。

相关问题