我有一个switch语句,其中每个case都有唯一的代码,以及除默认标签之外的所有案例共享的一些代码。 有不同的案例标签之间有共享命令的好方法吗?
编辑:代码示例
switch (c)
{
case '+':
command.type = ADD;
commands.push_back(command);
break;
case '-':
command.type = SUB;
commands.push_back(command);
break;
case '>':
command.type = INC;
commands.push_back(command);
break;
case '<':
command.type = DEC;
commands.push_back(command);
break;
case '.':
command.type = PUT;
commands.push_back(command);
break;
case ',':
command.type = GET;
commands.push_back(command);
break;
default: break;
答案 0 :(得分:11)
从std::map
char
command.type
保持command_table
类型。{
我们称之为switch (c)
{
case '+':
case '-':
case '>':
case '<':
case '.':
case ',':
command.type = command_table[c];
commands.push_back(command);
break;
default: break;
}
。
然后:
auto it = command_table.find(c);
if (it != command_table.end())
{
command.type = it.second;
commands.push_back(command);
}
或者,更短,并且还有一个额外的好处就是忘记案件更难:
logger.log('info', 'test message %s', 'my string');
答案 1 :(得分:5)
如下所示:
bool MyPushBackFlag = true;
switch (c)
{
case '+':
command.type = ADD;
break;
case '-':
command.type = SUB;
break;
case '>':
command.type = INC;
break;
case '<':
command.type = DEC;
break;
case '.':
command.type = PUT;
break;
case ',':
command.type = GET;
break;
default: MyPushBackFlag = false; break;
}
if (MyPushBackFlag)
commands.push_back(command);
答案 2 :(得分:2)
有时重构代码会增加复杂性......:)
#include <vector>
#include <array>
#include <iostream>
enum CommandType {
ADD, SUB, INC, DEC, PUT, GET
};
struct Command {
CommandType type;
};
std::vector<Command> commands;
using mapping = std::pair<char, CommandType>;
template<class T, class Iter, class Func>
bool dispatch(T &&t, Iter first, Iter last, Func &&f) {
auto i = std::find_if(first, last, [&t](auto &&pair) { return std::get<0>(pair) == t; });
if (i == last) {
return false;
}
f(std::get<1>(*i));
return true;
}
template<class T, std::size_t N, class Func>
bool dispatch(char t, std::array<mapping, N> const &range, Func &&f) {
return dispatch(t, range.begin(), range.end(), std::forward<Func>(f));
}
bool my_switch(char c) {
return dispatch(c,
std::array<mapping, 6> {{
{'+', ADD},
{'-', SUB},
{'>', INC},
{'<', DEC},
{'.', PUT},
{',', GET}
}}, [](auto type) {
Command command{};
command.type = type;
commands.push_back(command);
std::cout << "dispatched: " << command.type << std::endl;
})
or [](char c) {
std::cout << "invalid option " << c << std::endl;
return false;
}(c);
}
int main() {
my_switch('+');
my_switch('<');
my_switch('U');
}
答案 3 :(得分:0)
我有一个switch语句,其中每个case都有唯一的代码,以及除默认标签之外的所有案例共享的一些代码。
对于您的特定示例案例,不同情况之间的唯一区别在于数据而不是执行,地图可能更合适(请参阅molbdnilo's answer)。
通常,如果地图不合适(即代码路径的执行不同),您可以使用这种很少使用的原始控制结构goto
:
switch( c )
{
case '+': command.type = ADD; break;
case '-': command.type = SUB; break;
case '>': command.type = INC; break;
case '<': command.type = DEC; break;
case '.': command.type = PUT; break;
case ',': command.type = GET; break;
default:
goto no_match; // or return from function if appropriate
}
commands.push_back( command );
no_match:
//...
这比标志变量更清晰,更容易阅读 - 尽管这只是我的看法。
答案 4 :(得分:0)
我们可以不实际使用goto
而产生效果。
#define GOTO_END(...) { __VA_ARGS__; } if(false)
#define END {}
switch(c)
{
case '+': GOTO_END(command.type = ADD)
case '-': GOTO_END(command.type = SUB) // if `c == '-'` then jump to END
case '>': GOTO_END(command.type = INC)
case '<': GOTO_END(command.type = DEC)
case '.': GOTO_END(command.type = PUT)
case ',': GOTO_END(command.type = GET)
END // <--- must not be forgotten
commands.push_back(command);
default: break;
}