1

我的小组正在对 for 循环构造进行一些讨论和强烈的感受。

我喜欢这样的循环:

   size_t x;
   for (x = 0; x < LIMIT; ++x) {
      if (something) {
          break;
      }
      ...
   }

   // If we found what we're looking for, process it.
   if (x < LIMIT) {
       ...
   }

但其他人似乎更喜欢布尔标志,如:

   size_t x;
   bool found = false;
   for (x = 0; x < LIMIT && !found; ++x) {
      if (something) {
          found = true;
      }
      else {
          ...
      }
   }

   // If we found what we're looking for, process it.
   if (found) {
       ...
   }

(并且,在语言允许的情况下,使用“for (int x = 0; ...”。)

第一种样式有一个更少的变量来跟踪和一个更简单的循环头。尽管以“重载”循环控制变量和(有些人会抱怨)使用 break 为代价。

第二种风格明确定义了变量的角色,但更复杂的循环条件和循环体(设置了 else 或 continue after found ,或循环平衡中的“if (!found)”)。

我认为第一种风格在代码复杂性上胜出。我正在寻找更广泛受众的意见。指向更容易阅读和维护的实际研究的指针会更好。“没关系,把它排除在你的标准之外”也是一个很好的答案。

OTOH,这可能是错误的问题。我开始认为正确的规则是“如果你必须打破一个 for,那真的是一段时间。”

bool found = false;
x = 0;
while (!found  && x < LIMIT) {
    if (something) {
        found = true;
        ...handle the thing...
    }
    else {
        ...    
    }
    ++x;
}

执行前两个示例的操作,但行数更少。不过,它确实将 x 的初始化、测试和增量分成了三行。

4

8 回答 8

4

在这种情况下,我实际上敢建议考虑 GOTO 以打破循环:

   for (size_t x = 0; x < LIMIT && !found; ++x) {
      if (something) 
          goto found;

      else {
          ...
      }
    }

    // not found
           ...

      return;

    found:

       ...
      return;

我认为这种形式既简洁又易读。它在许多简单的情况下可能会有一些好处(例如,当这个函数中没有共同处理时,在发现/未发现的情况下)。

关于 goto 收到的普遍皱眉头,我发现这是对Dijkstra 最初主张的常见误解:他的论点支持结构化循环子句,如 for 或 while,而不是原始的 loop-via-goto,它仍然有很多存在1968. 甚至全能的 Knuth最终都说——

我提出的新道德也许可以这样表述:“如果程序文档解释了转换是什么,那么与易于理解的转换有关的某些陈述是可以接受的。”

这里的 其他人偶尔也会有同样的想法。

于 2009-09-15T14:46:40.043 回答
2

我更喜欢一个完全不同的:

       for (int x = 0; x < LIMIT; ++x) {
          if (something) {
              // If we found what we're looking for, process it.
              ...
              break;
          }
          ...
       }

看来你提到一个或另一个没有任何麻烦...... ;-)

  • 没有重复条件或可读性问题
  • 没有额外的变量
于 2009-09-15T14:01:52.190 回答
2

虽然我不同意额外的 else 确实使第二个更复杂,但我认为这主要是美学问题并符合您的标准。

就个人而言,我可能不喜欢休息和继续,所以我更有可能使用 found 变量。

另外,请注意,您可以将找到的变量添加到第一个实现并执行

if(something)
{
   found = true;
   break;
}

如果你想以额外的变量为代价来避免变量重载问题,但仍然想要简单的循环终止符......

于 2009-09-15T13:52:46.180 回答
2

前一个例子重复了x < LIMIT条件,而后者没有。

对于前者,如果你想改变那个条件,你必须记住在两个地方做。

于 2009-09-15T13:53:45.757 回答
1

我没有提到手(-1!-1!),但我似乎记得有多个退出点(来自函数,来自循环)已被证明会导致可维护性问题(我曾经知道为英国军方编写代码的人,这是 Verboten 这样做的)。但更重要的是,正如 RichieHindle 指出的那样,重复条件是一件坏事,它要求通过更改一个而不是另一个来引入错误。

如果你以后不使用这个条件,我也不会被打扰。既然你是,第二个就是要走的路。

于 2009-09-15T13:56:58.070 回答
0

这种论点以前(可能很多次)已经在这里争论过,例如在这个问题中。

有些人会争辩说代码的纯度是最重要的,他们会痛苦地抱怨你的第一个选项在所有情况下都没有相同的后置条件。

我要回答的是“胡说八道!”。我是一个实用主义者,而不是一个纯粹主义者。我和下一位工程师一样反对过多的意大利面条代码,但是我在 for 循环中看到的一些可怕的终止条件比在循环中使用几个中断要糟糕得多。

我将永远追求代码的可读性而不是“纯度”,仅仅是因为我必须维护它。

于 2009-09-15T13:54:41.473 回答
-1

这看起来像是一个while循环的地方。For 循环无论如何都是在 While 循环之上的语法糖。一般规则是,如果您必须跳出 For 循环,则改用 While 循环。

于 2009-09-15T13:51:33.680 回答
-5
package com.company;

import java.io.*;
import java.util.Scanner;

public class Main {


// "line.separator" is a system property that is a platform independent and it is one way
// of getting a newline from your environment.
private static String NEWLINE = System.getProperty("line.separator");


public static void main(String[] args) {
    // write your code here

    boolean itsdone = false;

    String userInputFileName;
    String FirstName = null;
    String LastName = null;
    String user_junk;
    String userOutputFileName;
    String outString;

    int Age = -1;
    int rint = 0;
    int myMAX = 100;
    int MyArr2[] = new int[myMAX];
    int itemCount = 0;
    double average = 0;
    double total = 0;
    boolean ageDone = false;


    Scanner inScan = new Scanner(System.in);

    System.out.println("Enter First Name");

    FirstName = inScan.next();

    System.out.println("Enter Last Name");

    LastName = inScan.next();


    ageDone = false;
    while (!ageDone) {
        System.out.println("Enter Your Age");
        if (inScan.hasNextInt()) {
            Age = inScan.nextInt();
            System.out.println(FirstName + " " + LastName + " " + "is " + Age + " Years old");
            ageDone = true;
        } else {
            System.out.println("Your Age Needs to Have an Integer Value... Enter an Integer Value");
            user_junk = inScan.next();
            ageDone = false;
        }
    }

    try {
        File outputFile = new File("firstOutFile.txt");

        if (outputFile.createNewFile()){
            System.out.println("firstOutFile.txt was created"); // if file was created
        }
        else {
            System.out.println("firstOutFile.txt existed and is being overwritten."); // if file had already existed
        }

        // --------------------------------
        // If the file creation of access permissions to write into it
        // are incorrect the program throws an exception
        //

        if ((outputFile.isFile()|| outputFile.canWrite())){
            BufferedWriter fileOut = new BufferedWriter(new FileWriter(outputFile));

            fileOut.write("==================================================================");

            fileOut.write(NEWLINE + NEWLINE +" You Information is..." + NEWLINE + NEWLINE);

            fileOut.write(NEWLINE +  FirstName + " " + LastName + " " + Age + NEWLINE);

            fileOut.write("==================================================================");

            fileOut.close();

        }
        else {
            throw new IOException();
        }

    } // end of try
    catch (IOException e) { // in case for some reason the output file could not be created
        System.err.format("IOException: %s%n", e);
        e.printStackTrace();
    }
} // end main method
}
于 2018-05-14T13:50:31.177 回答