代码之家  ›  专栏  ›  技术社区  ›  Lucas

使用goto来打破两个循环是合法的吗?

  •  19
  • Lucas  · 技术社区  · 15 年前

    我正在解决问题9 Project Euler .在我的解决方案中,我使用了一个“goto”语句来分解两个for循环。问题如下:

    毕达哥拉斯三位一体是三个自然数的集合,即b c,其中,

    a^ 2+b^ 2=c^ 2

    例如,3^2+4^2=9+16=25=52。

    只有一个毕达哥拉斯三位一体,A+B+C=1000。 找到产品ABC。

    我的解决方案是在C++中:

    int a,b,c;
    const int sum = 1000;
    int result = -1;
    for (a = 1; a<sum; a++){
        for (b = 1; b < sum; b++){
                c = sum-a-b;
                if (a*a+b*b == c*c){
                    result = a*b*c;
                    goto found;
                }
        }   
    }
    found:
    std::cout << "a:" << a << std::endl;
    std::cout << "b:" << b << std::endl;
    std::cout << "c:" << c << std::endl;
    std::cout <<"Result:" << result << std::endl;
    

    因为“Goto”语句在C++程序员中不是很流行,所以我想知道,如果这可以被认为是“GOTO”的合理使用。或者如果有更好的解决方案来解决不需要“转到”的问题。我所说的解决方案并不是避免“goto”,而是以改进算法的方式避免“goto”。

    7 回复  |  直到 9 年前
        1
  •  46
  •   Alex Martelli    15 年前

    return 是“结构化的” goto 很多程序员都认为这是可以接受的!所以:

    static int findit(int sum, int* pa, int* pb, int* pc)
    {
        for (int a = 1; a<sum; a++) {
            for (int b = 1; b < sum; b++) {
                int c = sum-a-b;
                if (a*a+b*b == c*c) {
                    *pa = a; *pb = b; *pc = c;
                    return a*b*c;
            }
        }
        return -1;    
    }
    
    int main() {
        int a, b, c;
        const int sum = 1000;
        int result = findit(sum, &a, &b, &c);
        if (result == -1) {
            std::cout << "No result!" << std::endl;
            return 1;
        }
        std::cout << "a:" << a << std::endl;
        std::cout << "b:" << b << std::endl;
        std::cout << "c:" << c << std::endl;
        std::cout <<"Result:" << result << std::endl;
        return 0;
    }
    
        2
  •  18
  •   StackedCrooked    9 年前

    在我看来,这是可以使用的 goto 在这种情况下。

    顺便说一句,屈尊的反哥特的说教通常来自于那些只会重复别人所说或读到的东西的人。

        3
  •  6
  •   Community Alex Howansky    7 年前

    this question 关于打破2个循环。有比使用goto更好的答案。

    提供的最佳答案是将第二个循环放入一个函数中,并从第一个循环内部调用该函数。

    从mquander的响应复制的代码

    public bool CheckWhatever(int whateverIndex)
    {
        for(int j = 0; j < height; j++)
        {
            if(whatever[whateverIndex][j]) return false;
        }
    
        return true;
    }
    
    public void DoubleLoop()
    {
        for(int i = 0; i < width; i++)
        {
            if(!CheckWhatever(i)) break;
        }
    }
    

    虽然我觉得在这种情况下使用Goto并没有杀死小猫那么糟糕。但很接近。

        4
  •  4
  •   Blixt    15 年前

    我想不出更好的选择。但另一种选择是不使用 goto 会修改第一个 for -循环:

    for (a = 1; a<sum && result == -1; a++){
    

    然后 break 在第二个 对于 -循环。如果结果永远不会 -1 第二次之后 对于 -循环已被中断 打破 .

        5
  •  4
  •   i_am_jorf    15 年前

    你可以申报 bool found = false 在顶部,然后添加 && !found 到您的for循环条件(之后 a < sum b < sum )然后将“发现”设置为“真”,即当前的GoTo所在位置。然后使输出条件为“发现为真”。

        6
  •  3
  •   Community Alex Howansky    7 年前

    我刚在“相关”侧边栏上找到这个。一个有趣的线索,但特别是, this 是我问题的答案。

        7
  •  1
  •   Sur3    13 年前
    int a,b,c,sum = 1000;
    for (a = 1; a<sum; ++a)
     for (b = 1; b<sum; ++b){
      c = sum-a-b;
      if (a*a+b*b == c*c) sum = -a*b*c;
     }
    printf("a: %d\n",a-1);
    printf("b: %d\n",b-1);
    printf("c: %d\n",c);
    printf("Result: %d\n",-sum);
    

    也优化了结果。P

    不管怎样,我喜欢哥特人!