嵌套太深了

时间:2012-07-16 15:57:44

标签: c++

我有一些不典型的问题。我向用户提供sendText()函数。他可以输入例如

sendText( "mytext{newline}text{up}" )

{text}是允许用户发送的特殊密钥。有很多特殊键可用。

所以我的第一步是在{}括号之间获取字符串并创建:

if( _specialKey == "newline" ) {
    // action for VK_RETURN
} else if( _specialKey == "up" ) {
    // action for VK_UP
} else .....

示例:

if( specialKey == "n" ) {
    // enter click
    unsigned short key = VK_RETURN;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "n+" ) {
    // enter down
    inputs.push_back( keyDown( VK_RETURN ) );

    return 2;
} else if( specialKey == "n-" ) {
    // enter up
    inputs.push_back( keyUp( VK_RETURN ) );

    return 2;
} else if( specialKey == "t" ) {
    // tabulator click
    unsigned short key = VK_TAB;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "t+" ) {
    // tabulator down
    inputs.push_back( keyDown( VK_TAB ) );

    return 2;
} else if( specialKey == "t-" ) {
    // tabulator up
    inputs.push_back( keyUp( VK_TAB ) );

    return 2;
} else if( specialKey == "caps" ) {
    // caps lock click
    unsigned short key = VK_CAPITAL;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "caps+" ) {
    // caps lock down
    inputs.push_back( keyDown( VK_CAPITAL ) );

    return 2;
} else if( specialKey == "caps-" ) {
    // caps lock up
    inputs.push_back( keyUp( VK_CAPITAL ) );

    return 2;
} else if( specialKey == "ralt" ) {
    // right alt click
    unsigned short key = VK_RMENU;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "ralt+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_RMENU ) );

    return 2;
} else if( specialKey == "ralt-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_RMENU ) );

    return 2;
} else if( specialKey == "lalt" ) {
    // right alt click
    unsigned short key = VK_LMENU;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "lalt+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_LMENU ) );

    return 2;
} else if( specialKey == "lalt-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_LMENU ) );

    return 2;
} else if( specialKey == "rctrl" ) {
    // right alt click
    unsigned short key = VK_RCONTROL;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "rctrl+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_RCONTROL ) );

    return 2;
} else if( specialKey == "rctrl-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_RCONTROL ) );

    return 2;
} else if( specialKey == "lctrl" ) {

但编译说:

fatal error C1061: compiler limit : blocks nested too deeply

我解决它的第一个想法是定义一个地图,它将存储映射到某个整数的所有特殊键(作为字符串)。然后我可以做:

switch( map[key] ) {
    case 0:
    ...
}

但我不确定编译器是否也不会抱怨它。有很多要改变,所以我不想改变它没有结果。

或许你还有其他更好的想法吗?

感谢。

3 个答案:

答案 0 :(得分:6)

您有超过127个else if块。虽然这应该编译,而且它肯定是微软C ++编译器中的一个错误,但是你的代码还有一个很强烈的气味。

您正在控制流中存储数据,这128个块中的绝大多数都是冗余复制和粘贴块。如果可能的话,你不应该这样做。分离您的代码和数据,对特殊情况使用控制流,同时将所有常见情况重构为一个哈希映射,将其作为一种类型处理。

答案 1 :(得分:5)

您可以使用以下地图:map<string, int>。一个元素就像pair<string,int>("newline", VK_RETURN>

map<string, int> NameToKey;
NameToKey.insert(make_pair("newline", VK_RETURN));

在开关案例中使用相同的内容,如:

map<string,int>::const_iterator iter = NameToKey.find(_specialKey);
switch(iter->second)
{
case VK_RETURN: // Handle as "newline"
   ;
 }

答案 2 :(得分:2)

有点OOP而不是指向函数方式的指针。

class ICommand
{
  public:
  virtual void execute() const =0;
  virtual void ~ICommand(){};
};

class KeyUpCommand : public ICommand
{
  DWORD key_; //not suare about win api here
  public:
  KeyUpCommand(key) : key_(key) {};
  virtual void execute() const
  {
     keyUp(key_);
  };
};

class KeyDownCommand : public ICommand
{
  DWORD key_; //not suare about win api here
  public:
  KeyDownCommand(key) : key_(key) {};
  virtual void execute() const
  {
     keyDown(key_);
  };
};


int main()
{
  std::map<std::string, ICommand *> commands;
  commands["t-"]=new KeyUpCommand(VK_TAB);

  //execute now
  std::map<std::string, ICommand *>::const_iterator iter = commands.find(_specialKey);
  iter->second->execute();
};