我听说使用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);
}
}
答案 0 :(得分:10)
while (true)
没问题。保持它。
如果你有更自然的终止条件,我会说要使用它,但在这种情况下,正如其他答案所证明的那样,摆脱while (true)
会使代码更难理解。
答案 1 :(得分:3)
有一个单一条目单一退出(SESE)思想学派,建议您不要使用break
,continue
或滥用例外对某些滥用价值做同样的事情。我相信这里的想法不是你应该使用一些辅助标志变量,而是要明确说明循环的后置条件。这使得以前推理循环变得易于理解。显然使用从理论上说是理性的形式,所以它对未洗过的群众(比如我自己)不受欢迎。
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
测试,而是将arraySize
,k
和randomData
封装在一个对象中,并创建一个从输入中读取数据的方法,如果用户退出,则返回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个故事中跳出来......