如何在一个switch中实现多个case的一些独占语句和一些公用语句?
How to achieve some exclusive statements and some common statements for multiple cases in a switch?
我有一个 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;
- 将标志设置为 true
- 在switch的默认情况下,设置flag为false
- 运行 标志为真时的通用代码。
类似于以下内容:
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);
保持 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);
}
I have a switch statement where each case has unique code, and some code that is shared between all cases except the default label.
对于您的特定示例案例,不同案例之间的唯一区别在于数据而非执行,地图可能更合适(参见 )。
一般来说,当映射不合适时(即当代码路径在执行时不同时),您可以使用这种很少使用的基本控制结构,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:
//...
这比标志变量更清晰易读 - 虽然这只是我的意见。
有时重构代码只会增加复杂性...:)
#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');
}
我们可以在不实际使用的情况下产生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;
}
我有一个 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;
- 将标志设置为 true
- 在switch的默认情况下,设置flag为false
- 运行 标志为真时的通用代码。
类似于以下内容:
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);
保持 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);
}
I have a switch statement where each case has unique code, and some code that is shared between all cases except the default label.
对于您的特定示例案例,不同案例之间的唯一区别在于数据而非执行,地图可能更合适(参见
一般来说,当映射不合适时(即当代码路径在执行时不同时),您可以使用这种很少使用的基本控制结构,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:
//...
这比标志变量更清晰易读 - 虽然这只是我的意见。
有时重构代码只会增加复杂性...:)
#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');
}
我们可以在不实际使用的情况下产生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;
}