对于我的任务,我正在存储用户登录信息。我接受了一个字符串,这是命令。该命令可以是创建,登录,删除等。共有10个选项,即10种不同的字符串。任何人都可以解释一个更有效的方式来写这个而不是10 if if else if语句?基本上除了使用一堆if (string == "one")
,else if (string == "two")
之外,我应该如何格式化/构造事物。谢谢
答案 0 :(得分:1)
您可以使用为您进行比较的地图。
这样的事情:
初始化地图:
std::map<std::string, std::function<void(std::string&)>> map;
map["login"] = std::bind(&Class::DoLogin, this, std::placeholders::_1);
map["create"] = std::bind(&Class::DoCreate, this, std::placeholders::_1);
接收消息:
map.at(rx.msg_type)(rx.msg_data);
<强>处理程序:强>
void Class::DoLogin(const std::string& data)
{
// do login
}
答案 1 :(得分:1)
我希望您的讲师希望您将功能提取到另一个可重复使用的功能:
string action;
command = CreateAction(action);
command.Do(...);
当然,在你的CreateAction类中,你仍然需要有条件来确定需要创建哪些命令。
AbstractCommand CreateAction(action)
{
if (action == "login")
return LoginCommand();
else if (action == "remove")
return RemoveCommand();
..... etc etc
}
如果你真的想要摆脱所有的条件,你可以创建一些自我注册的命令,但这涉及更多的代码和类......
等内容答案 2 :(得分:1)
您可以使用函数指针和查找表。
typedef void (*Function_Pointer)(void);
void Create(void);
void Login(void);
void Remove(void);
struct Function_Option_Entry
{
const char * option_text;
Function_Pointer p_function;
};
Function_Option_Entry option_table[] =
{
{"one", Create},
{"two", Login},
{"three", Remove},
};
const unsigned int option_table_size =
sizeof(option_table) / sizeof(option_table[0]);
//...
std::string option_text;
//...
for (i = 0; i < option_table_size; ++i)
{
if (option_text == option_table[i].option_text)
{
option_table[i].p_function();
break;
}
}
答案 3 :(得分:1)
使用switch
和简单的哈希函数
您需要使用哈希函数,因为C和C ++只允许切换整数值。
template<size_t N> constexpr char myhash(const char &x[N]) { return x[0] ^ (x[1]+63); }
char myhash(const string& x) { return x.size() ? x[0] ^ (x[1]+63) : 0; }
switch(myhash(s)) {
case myhash("one"):
if(s != "one") goto nomatch;
// do things
break;
case myhash("two"):
if(s != "two") goto nomatch;
// do things
break;
default:
nomatch:
// No match
}
如果您不使用std::string
,则需要进行轻微调整。
答案 4 :(得分:1)
我建议你为每个特定的字符串创建一个函数。例如,如果您收到一个字符串&#34;创建&#34;你将调用函数doCreate(),如果你收到一个字符串&#34; login&#34;然后你调用函数doLogin()
对这些功能的唯一限制是所有这些功能必须具有相同的签名。在上面的一个例子中,它是这样的:
typedef void (*func_t) ();
这个想法是从字符串到这些函数创建一个std :: map。所以你不必写10个左右,因为你可以通过特定字符串名称的名称从地图中简单地选择正确的函数。让我通过一个小例子来解释它:
typedef void (*func_t) ();
void doCreate()
{
std::cout << "Create function called!\n";
}
void doLogin()
{
std::cout << "Login function called!\n";
}
std::map<std::string, func_t> functionMap;
void initMap()
{
functionMap["create"] = doCreate;
functionMap["login"] = doLogin;
}
int main()
{
initMap();
std::string str = "login";
functionMap[str](); // will call doLogin()
str = "create";
functionMap[str](); // will call doCreate()
std::string userStr;
// let's now assume that we also can receive a string not from our set of functions
std::cin >> userStr;
if (functionMap.count(userStr))
{
functionMap[str](); // now we call doCreate() or doLogin()
}
else
{
std::cout << "Unknown command\n";
}
return 0;
}
我希望它会在某种程度上帮助你=)
答案 5 :(得分:0)
也许您可以创建std::map<std::string, int>
并使用地图查找来获取已传递的命令的代码 - 您可以稍后打开该数字。或者创建enum Command
并拥有std::map<std::string, Command>
并使用切换。
示例:
enum Command
{
CREATE,
LOGIN,
...
};
std::map<std::string, Command> commandNameToCode;
// fill the map with appropriate values
commandNameToCode["create"] = Command::CREATE;
// somehow get command name from user and store in the below variable (not shown)
std::string input;
// check if the command is in the map and if so, act accordingly
if(commandNameToCode.find(input) != commandNameToCode.end())
{
switch(commandNameToCode[input])
{
case CREATE:
// handle create
break;
...
}
}