如何从Java中的循环中删除while(true)?

时间:2009-10-03 21:55:43

标签: java infinite-loop

我听说使用while(true)是一种糟糕的编程习惯。

所以,我编写了以下代码来获取用户的一些数字(默认值)。但是,如果用户碰巧输入-1,那么它将退出程序。

如何在没有片刻(真实)的情况下写出来?我可以想到一个条件让while循环关闭会立即被捕获而不会继续直到下一次迭代?

以下是我现在的方式:

 public static void main(String[] args)
    {
        System.out.println("QuickSelect!");

        while (true)
        {
            System.out.println("Enter \"-1\" to quit.");

            int arraySize = 10;
            System.out.print("Enter the size of the array (10): ");
            String line = input.nextLine();
            if (line.matches("\\d+"))
            {
                arraySize = Integer.valueOf(line);
            }

            if (arraySize == -1) break;

            int k = 1;
            System.out.print("Enter the kth smallest element you desire (1): ");
            line = input.nextLine();
            if (line.matches("\\d+"))
            {
                k = Integer.valueOf(k);
            }

            if (k == -1) break;

            List<Integer> randomData = generateRandomData(arraySize, 1, 100);

            quickSelect(randomData, k);
        }
    }

8 个答案:

答案 0 :(得分:10)

while (true)没问题。保持它。

如果你有更自然的终止条件,我会说要使用它,但在这种情况下,正如其他答案所证明的那样,摆脱while (true)会使代码更难理解。

答案 1 :(得分:3)

有一个单一条目单一退出(SESE)思想学派,建议您不要使用breakcontinue或滥用例外对某些滥用价值做同样的事情。我相信这里的想法不是你应该使用一些辅助标志变量,而是要明确说明循环的后置条件。这使得以前推理循环变得易于理解。显然使用从理论上说是理性的形式,所以它对未洗过的群众(比如我自己)不受欢迎。

public static void main(String[] args) {
    ...
    do {
        ...
        if (arraySize == -1)  {
            ...
            if (k != -1) {
                ...
            }
        }
    } while (arraySze == -1 || k == -1);
    ...
}

真正的代码会更复杂,您自然会(!)将输入,输出和核心“业务”逻辑分开,这样可以更容易地看到正在发生的事情。

答案 2 :(得分:2)

    bool exit = false;
while (!exit) {
    ...
    ...
    if (k == -1) {
        exit = true;            
    }
    else {         
        List <Integer> ....;
        quickselect(.......);
    }
}

但正如之前所说,在这种情况下,你的while循环是一个有效的用法。其他选项将简单地构建在if语句上以检查boolean和exit。

答案 3 :(得分:1)

虽然这样的循环在技术上不是错误的,但有些人会认为它不像以下那样可读:

bool complete = false;

while (!complete)
{

    if (arraySize == -1)
    {
        complete = true;
        break;
    }
}

此外,有时候有一个安全循环计数器可以检查以确保循环没有经过,例如1亿次迭代,或者比循环体预期的要大得多的数字。这是一种确保错误不会导致程序“挂起”的安全方法。相反,你可以给用户一个友好的“我们很抱歉,但你发现了一个错误..程序现在将退出..”你将'complete'设置为true并结束程序或执行其他错误处理。我在生产代码中已经看过这个,可能会也可能不会是你会使用的东西。

答案 4 :(得分:0)

如果您真的不喜欢while(true),可以随时前往for(;;)。我更喜欢后者,因为它看起来不那么多余了。

答案 5 :(得分:0)

虽然(true)在这里完全没问题,因为条件确实是“当用户不想退出”时!

或者,您可以在一行上提示两个输入以简化逻辑,并使用“q”进行退出:这允许您将循环重构为“while(!line.equals(”q“))”。

答案 6 :(得分:0)

问题在于你在循环中做了很多事情,而不是将功能分成简单的方法。

如果您想坚持使用程序方法,可以将数组大小和k的读数移动到单独的方法中,并使用赋值结果为赋值的事实:

    for (int arraySize; ( arraySize = readArraySize ( input ) ) != -1;) {
        final int k = readKthSmallestElement ( input );

        List<Integer> randomData = generateRandomData(arraySize, 1, 100);

        quickSelect(randomData, k);
    }

然而,这仍然有点难看,并没有很好的封装。因此,不要对单独的变量进行两次!= -1测试,而是将arraySizekrandomData封装在一个对象中,并创建一个从输入中读取数据的方法,如果用户退出,则返回QuickSelect对象或null

    for ( QuickSelect select; ( select = readQuickSelect ( input ) ) != null; ) {
        select.generateRandomData();
        select.quickSelect();
    }        

您甚至可能想要进入从输入创建一系列QuickSelect对象的下一个阶段,每个对象都封装一次迭代的数据:

    for ( QuickSelect select : new QuickSelectReader ( input ) ) {
        select.generateRandomData();
        select.quickSelect();
    }        

其中QuickSelectReader实现Iterable,迭代器具有创建QuickSelect对象的逻辑,该对象封装了arraySize,k,列表和快速选择操作。但最终会比程序变体的代码多得多。

如果我想在其他地方重复使用它,我只会这样做;仅仅为了使main()漂亮是不值得的。

另请注意,"-1"与正则表达式"\\d+"不匹配,因此您确实存在无限循环。

答案 7 :(得分:0)

while(true){}在某些情况下非常有用..如果你说错误使用,你应该从1000个故事中跳出来......