[英]Simple text menu in C++
I am writing a silly little app in C++ to test one of my libraries. 我正在用C ++写一个愚蠢的小应用程序来测试我的一个库。 I would like the app to display a list of commands to the user, allow the user to type a command, and then execute the action associated with that command. 我希望该应用程序向用户显示命令列表,允许用户键入命令,然后执行与该命令关联的操作。 Sounds simple enough. 听起来很简单。 In C# I would end up writing a list/map of commands like so: 在C#中,我最终将像这样编写命令列表/映射:
class MenuItem
{
public MenuItem(string cmd, string desc, Action action)
{
Command = cmd;
Description = desc;
Action = action;
}
public string Command { get; private set; }
public string Description { get; private set; }
public Action Action { get; private set; }
}
static void Main(string[] args)
{
var items = new List<MenuItem>();
items.Add(new MenuItem(
"add",
"Adds 1 and 2",
()=> Console.WriteLine(1+2)));
}
Any suggestions on how to achieve this in C++? 关于如何在C ++中实现这一点的任何建议? I don't really want to define separate classes/functions for each command. 我真的不想为每个命令定义单独的类/函数。 I can use Boost, but not TR1. 我可以使用Boost,但不能使用TR1。
A very common technique is to use function pointers, or boost::function, indexed by the item name, or by having a vector of them and indexing by the item index for this job. 一种非常常见的技术是使用函数指针或boost :: function,通过项目名称进行索引,或者通过使用它们的向量并通过此项工作的项目索引进行索引。 Simple example using the item name: 使用项目名称的简单示例:
void exit_me(); /* exits the program */
void help(); /* displays help */
std::map< std::string, boost::function<void()> > menu;
menu["exit"] = &exit_me;
menu["help"] = &help;
std::string choice;
for(;;) {
std::cout << "Please choose: \n";
std::map<std::string, boost::function<void()> >::iterator it = menu.begin();
while(it != menu.end()) {
std::cout << (it++)->first << std::endl;
}
std::cin >> choice;
if(menu.find(choice) == menu.end()) {
/* item isn't found */
continue; /* next round */
}
menu[choice](); /* executes the function */
}
C++ doesn't have a lambda feature yet, so you really have to use functions for this task, sadly. C ++还没有lambda功能,因此遗憾的是,您确实必须使用函数来完成此任务。 You can use boost::lambda, but note it is just simulating lambdas, and nowhere near as powerful as a native solution: 您可以使用boost :: lambda,但是请注意,它只是在模拟lambdas,远没有本机解决方案强大:
menu["help"] = cout << constant("This is my little program, you can use it really nicely");
Note the use of constant(...), since otherwise boost::lambda wouldn't notice that this is supposed to be a lambda expression: The compiler would try to output the string using std::cout, and assign the result (an std::ostream reference) to menu["help"]. 请注意使用constant(...),因为否则boost :: lambda不会注意到这应该是lambda表达式:编译器将尝试使用std :: cout输出字符串,并分配结果(菜单[“ help”]的std :: ostream引用)。 You can still use boost::function, since it will accept everything returning void and taking no arguments - including function objects, which is what boost::lambda creates. 您仍然可以使用boost :: function,因为它将接受所有返回void并且不带参数的东西-包括函数对象,这就是boost :: lambda创建的。
If you really don't want separate functions or boost::lambda, you can just take print out a vector of the item names, and then switch
on the item number given by the user. 如果您确实不想要单独的功能或boost :: lambda,则只需打印出项目名称的向量,然后switch
用户指定的项目编号即可。 This is probably the easiest and most straight forward way of doing it. 这可能是最简单,最直接的方法。
Why not just port the C# code to C++? 为什么不只是将C#代码移植到C ++? There's a little work to be done, but something like this should get most of your work done: 有一些工作要做,但是这样的事情应该可以完成大部分工作:
using std::string;
class MenuItem
{
public:
MenuItem(string cmd, string desc, boost::function<bool()> action):Command(cmd),
Description(desc),
Action(action)
{}
boost::function<bool()> GetAction() { return Action; }
string GetDescription() { return Description; }
string GetCommand() { return Command; }
private:
string Command;
string Description;
boost::function<bool()> Action;
}
With that defined, your main() can use a std::list, and use a simple while() loop that checks the exit value of the MenuItem's Action to determine if it should exit. 定义好之后,您的main()可以使用std :: list,并使用一个简单的while()循环来检查MenuItem的Action的退出值,以确定是否应退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.