【问题标题】:Acceptable use of a label and 'goto'? [closed]标签和“goto”的可接受使用? [关闭]
【发布时间】:2015-07-04 10:32:21
【问题描述】:

我正在为编译器编写分词器。我有一个循环字符的while循环,然后是一个检查某些条件的开关。然后我需要退出两个块来写入令牌:

Token token;

while (peekChar() != '\0')
{
    switch (c = nextChar())
    {
        case '(':
            token = Token(TOKEN_LEFT_PAREN, currentLine);
            goto MakeToken;
        // ... every other character, some with lots of logic
    }
}

MakeToken:
    // write the token

这是一种可接受的标签使用方式,还是有更好的方法?我已经学会将标签视为糟糕的做法,但肯定有它们的用途(或者它们不会在标准中实现?)。谢谢。

【问题讨论】:

  • 支持 goto 语句仅是为了与旧代码库兼容。我不建议 goto 语句或标签。使用 goto 语句会破坏程序结构,通常一个 goto 语句是出现其他 goto 语句的原因。:)
  • 标签是一种工具。他们既不是善也不是恶。如果有意义就使用它们,如果没有意义就不要使用它们。

标签: c++ label goto


【解决方案1】:

一般来说,当我们想同时打破几个作用域时,意味着我们可以制作子函数;比如:

bool HandleChar(char c)
{
    switch (c)
    {
        case '(': {
                Token token = Token(TOKEN_LEFT_PAREN, currentLine);
                return true;
        }
        // ... every other character, some with lots of logic
    }
}

然后:

while (peekChar() != '\0')
{
   if (HandleChar(nextChar())) {
       break;
   }
}
// ...

【讨论】:

  • 谢谢 - 没想到那个方法,肯定会让代码更简单。
【解决方案2】:

您可以在此处使用break 实现相同的功能,而无需使用goto

我唯一一次在 C++ 中发现 goto 的一个稍微令人反感的案例是在一个复杂的状态机中,开发人员非常注意不要弄乱本地状态。

通常,解析器(或者更具体地说,标记器)是我进行意大利面条式编码的最后一个地方——如果有的话,这需要以更实用的方式使用 C++。

【讨论】:

    【解决方案3】:

    我相信这是接受 goto 的极少数示例之一,但您可以使用标志:

    Token token;
    bool flag = true;
    while ((peekChar() != '\0') && flag)
    {
        switch (c = nextChar())
        {
            case '(':
                token = Token(TOKEN_LEFT_PAREN, currentLine);
                flag = false;
            // ... every other character, some with lots of logic
        }
    }
    

    【讨论】:

    • 好的,谢谢。我不知何故进入了我的脑海,“中断”将允许 while 循环继续循环 - 谢谢!
    • 它会——这就是为什么flag被设置为false
    • 是的,我的错。编辑它。
    • 哦,好吧 - 很高兴知道我不是一个彻头彻尾的白痴。谢谢@MarcusMüllerꕺꕺ
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多