对于switch语句中的所有情况都使用相同的命令?

时间:2017-04-21 14:44:14

标签: c++ goto

我有一个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;

5 个答案:

答案 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)

  • 将标志设为true
  • 在交换机的默认情况下,将标志设置为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);

答案 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;        
}