【问题标题】:Is it bad to use goto in this situation?在这种情况下使用 goto 不好吗?
【发布时间】:2015-06-04 18:04:19
【问题描述】:

我一直在开发一个基于控制台的计算器应用程序,我想使用 2 个函数来让它看起来更干净(我不希望 main 有太多行),所以我决定使用 goto 跳转从 main 到我的箔函数,然后另一个 goto 跳回到 main 的开头。我只是想知道这样做是否不安全。谢谢:)

void foileq()
{
    int a, b, c, d;
    printf("Enter the 4 numbers\n");
    cin >> a;
    cin >> b;
    cin >> c;
    cin >> d;
    cout << a * c << " " << a * d << " " << b * c << " " << b * d << endl;
}

int main()
{
    float a, b;
    string type = "";
BEGIN:
    {
        while (1)
        {
            printf("Add,subtract,multiply,divide,foil,power?\n");
            cin >> type;
            if (type == "foil")
            {
                goto FOIL;
                continue;

            }
            else
            {
                printf("Enter A number\n");
                cin >> a;
                printf("Enter another number\n");
                cin >> b;
                if (strcmp(type.c_str(), "add") == 0)
                    printf("%.2f\n", a + b);
                else if (strcmp(type.c_str(), "subtract") == 0)
                    printf("%.2f\n", a - b);
                else if (strcmp(type.c_str(), "multiply") == 0)
                    printf("%.2f\n", a * b);
                else if (strcmp(type.c_str(), "divide") == 0)
                    printf("%.2f\n", a / b);
                else if (strcmp(type.c_str(), "power") == 0)
                    printf("%.2f\n", pow(a, b));
            }
        }
    }
FOIL:
    foileq();
    goto BEGIN;
}

【问题讨论】:

  • 在这种情况下,我(不讨厌 goto)认为它很糟糕,主要是无限循环
  • float main()???
  • 请提供一个适当的例子 - 请参阅@NathanOliver 评论(对于否决票来说太糟糕了)
  • 是的,我不确定为什么我将它从通常的更改为浮动,我想 b/c 我在函数内部使用了浮动,但是是的,没有必要这样做。我看不出这个例子是怎么不合适的,因为它编译和运行良好,即使它通常是 int/void。
  • 不要使用goto 向后跳!这是规则之一,那些蹩脚的 MISRA 标准是正确的。

标签: c++ calculator


【解决方案1】:

如果您调用foileq(); 而不是goto FOIL;,行为将是相同的。在这种情况下,使用 goto 不会使事情更具可读性。 goto 在极少数情况下会使代码变得更好,而这不是其中之一。

此外,您当前编写的 continue 也不需要,因为它前面有 goto

【讨论】:

  • 我曾想过这样做,但如果我这样做了,它会首先调用它,不是吗? printf("请输入一个数字\n");辛 >> 一; printf("请输入另一个数字\n");辛 >> b;啊,我明白了,我知道为什么我添加了继续。我记得在执行foileq() 后程序关闭时出现问题,但我想我的第二个goto 解决了这个问题。
  • @Jeff 不,不会。 continue 会让你回到while 循环的开头。 goto FOIL;printf("Enter A number\n"); 也位于 if 语句的单独 then/else 范围内。
  • 我明白你现在在说什么了,是的,如果 type == "foil" 我可以这样做,然后在那里调用 foileq,没想到。
【解决方案2】:

“在这种情况下使用goto 不好吗?”

在任何情况下使用goto 几乎总是被认为不好。如果你使用它,不要向后跳,而只能向前跳。

以下内容(使用单个标签)可能没问题:

 int foo() {
     while(loop_condition_ok) {
         if(inner_operation_fails()) {
             goto hell;
         }
     }
     return 0;

 hell:
     return -1;
 }

【讨论】:

  • 啊,我明白了,使用 goto 后退是否有特定原因会被认为是有害的?
  • "goto ... 倒退是否有特定原因" 有很多,主要是goto 使您的代码混乱且不可读。通常,您只是不使用goto,而是使用适当的循环结构和breakcontinue 来跳过代码。
  • 当然do { /** break on failure**/ if(1condition) { break; } } whilefalse); 更好。 “Gotcha”实际上在哪里??
【解决方案3】:

GOTO 看似普遍的革命很大程度上归功于 Edsger Dijkstra 的信“Go To Statement被认为是有害的”。

(来源:while(1) .. break instead of goto

当 type == "foil" 时使用 while 循环退出

while( type != "foil" )

然后将 else 更改为 if( type !="foil" ) 以防止它在输入为箔时运行。

【讨论】:

  • 我一定会看一看这封信,谢谢。此外,这样的问题通常会收到 4 票否决票吗?我认为这是一个合适的问题,因为我没有经验并且以前从未使用过 goto。 o.o
  • @Jeff - 习惯上首先在 Internet(或 Stack Overflow)上搜索已经回答的问题。如果您不知道究竟要寻找什么,这有时会很困难。至少你得到了(一些)可以进一步帮助你的答案。
  • 没错,我确实得到了有用的答案,下次我会在提问之前做一些研究,对此感到抱歉。
  • @Jeff - 无需道歉。它发生在我们大多数人至少一次。
猜你喜欢
  • 2012-03-28
  • 1970-01-01
  • 2023-03-24
  • 2017-03-31
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多