20

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

毕达哥拉斯三元组是三个自然数 abc 的集合,其中,

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”,而是以改进算法的方式避免“goto”。

4

6 回答 6

46

returngoto是许多程序员认为更容易接受的“结构化” !所以:

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;
}
于 2009-06-21T17:45:37.290 回答
18

在我看来,goto在这种情况下使用它很好。

顺便说一句,对 goto 的居高临下的说教通常来自那些只是模仿他们听到别人说或在某处读到的东西的人。

于 2009-06-21T20:05:19.257 回答
6

请参阅有关打破 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 并不像杀死小猫那么糟糕。但它很接近。

于 2009-06-21T17:45:36.057 回答
4

我想不出更好的选择。但是一个不使用的替代方法goto是修改第一个for循环:

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

然后break退出第二个for循环。假设结果永远不会-1在第二个for循环被break.

于 2009-06-21T17:30:09.510 回答
4

您可以在顶部声明 a bool found = false,然后添加&& !found到您的 for 循环条件(在a < sumand之后b < sum),然后在当前 goto 所在的位置将 found 设置为 true。然后使您的输出以发现为真为条件。

于 2009-06-21T17:32:40.207 回答
1
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

反正我喜欢gotos!

于 2011-12-24T13:41:06.600 回答