为什么使用for循环而不是while循环?

可能重复:
迭代for循环或while循环?
循环在C – for()或while() – 这是最好的?

什么时候应该使用for循环而不是while循环?

我认为下面的循环是相同的,除了它们的语法。 如果是这样,那为什么select一个呢?

 int i; for (i = 0; i < arr.length; i++) { // do work } int i = 0; while (i < arr.length) { // do work i++; } 

在你的情况下,除了for循环中的less一行代码,你不会获得太多的东西。

但是,如果你这样声明循环:

 for(int i = 0; i < x; i++) 

你设法让i在循环的范围内,而不是让它逃到代码的其余部分。

此外,在一个while循环中,你有3个不同的地方的variables声明,条件和增量。 使用for循环,这一切都在一个方便,易于阅读的地方。

最后想到:
更重要的一点是 这两者之间有语义上的区别。 一般而言,循环意味着具有不确定数量的迭代。 (即直到文件被读取了,不pipe有多less行),for循环应该有更多的迭代次数。 (遍历集合中的所有元素,我们可以根据集合的大小来计算)。

有一个理由可以select:可读性。

通过使用for循环,您明确表示您的意图是执行某种types的操作,需要初始化,“步骤”操作和完成条件。

while另一方面,你只是说你需要完成条件。

当我不一定需要一个计数器的时候,我使用'while',例如当你正在从一个文件读取,而你正在等待达到EOF。 在这种情况下,“for”可能不是最好的select。 当你正在浏览一个数组时,我宁愿使用'for',因为它传达的意图更好。

for()和while()循环之间的一个显着区别是,while()循环中的“continue”语句将分支到循环的顶部,而for()循环中的一个将分支到第三部分for()子句[通常用于碰撞variables的条件]。

作为一名教师,我一直在以各种forms和forms思考这个问题。 我的build议总是归结为

  • 为了计算。 倒计时,倒计时。
  • while / do-while构造适用于所有其他条件。 c!=EOFdiff<0.02等。迭代器/枚举器是非常适合for循环的计数器。

即你的int=0; while( ... ) int=0; while( ... )是可怕的我的眼睛。

为什么select可口可乐百事可乐?

在WHILE和FOR循环之间,可以交替使用它们。 要成为一个纯粹主义者,你可以根据条件的性质作出决定。 如果你正在执行一个基于计数的循环,那么FOR循环将是最有意义的。

 for( cur = 0; cur < myList.Length; cur++ ){ doSomething( myList[cur] ); } 

如果你正在执行一个基于逻辑的循环,那么一个WHILE将会是最干净的实现

 Iterator i = myObject.getIterator(); while( i.hasNext() ){ doSomething( i.next() ); } 

正如你所说,原因是语义和美学,而不是performance(他们编译的代码往往是非常相似)。

也就是说, for具有已知迭代次数的循环而言,通常是这样的,然而这意味着条件不一定与循环内部所做的相关,或者在开始时不知道有多less迭代将有。

通常,我总是喜欢循环,即使在循环与计数无关的情况下也是如此,因为它将循环的维护定位在单个位置。 当别人出现并决定添加/修改循环时,如果他们正在使用FOR循环,那么修改的人通常可以确信,只要他们不弄乱FORexpression式内的项目, ,他们不会打破循环中的迭代。

然而,像while循环这样的东西需要程序员完全parsing循环体,并且了解它是如何迭代的,以确保它们在修改时保持循环维护代码不被修改和正确的顺序。

因此,我在有效需要FOR的中间部分的情况下使用WHILE。

它们在function上是相同的,然而,可以认为for循环不太容易出错,因为所有的循环function都在那里。 如果你有几行将我的声明,while声明和index迭代器分开,你可能会忘记,或者被它的使用方式弄糊涂了。 这当然都是主观的。

在编程的早期,stream行的数据结构是线性数组(aka向量),重复模式是遍历和使用数组中的每个元素。 所以通常这种情况是语言包含了这种模式的特定语法:for循环。 除了这个历史遗产,你可以使用while循环(现在好像F#等函数式语言,你宁愿使用List.map或List.fold 😉

这主要是一个可读性问题。 通常,当你有一个定义的值范围迭代时使用for循环。 当你不迭代的时候使用while循环,或者不知道什么时候你的退出条件是真的。

从java的angular度来看,我发现循环非常方便的集合:

 for (Object o : objects){ o.process(); } 

比以下更容易阅读:

 int i=0; while(i < objects.size()){ objects.get(i).process(); i++; } 

他们通常会编译到相同的最终结果。 大部分时间我都喜欢“为了”或“为了”。 写作

 for (;x<5;x++){ //do work } 

不是那么险恶,而是写作

 while(x<5){ x++ //do work } 

代替

 while(x<5){ //do work x++ } 

可能会混淆一些人,并导致一个错误的错误。

在像帕斯卡这样的语言中,for和while构造具有不同的应用。 你可以在Pascal中编写一个for循环,如下所示:

 for i := 1 to 5 do begin { some code here } end 

所以你明确地说我是递增1.在这里没有明确指定终止条件。 因此,只有在实际循环执行开始之前,您知道循环将运行一定的预定次数的地方,才可以使用for循环。 另一方面,在while循环的情况下,你可以指定一个明确的终止条件。

 i:=0; while (i<>5) do begin { some code here } i:=i+1; end 

因此,while循环更加灵活。 在C开发的时候,尽pipefor和while被支持,for构造的含义改变了,你可以使用布尔运算符来添加显式的终止条件。 因此,C语言和C语言中的while和for的function是相同的,因此它变得更多的是可读性问题而不是可用性问题。

纵观其他(非常好的)答案,有一点我没有看到。 (如果它确实发生了,我错过了,并道歉。)

我将给你看两个看起来语义相同的代码片段。

片段#1:

 for (int a = 0; a < arr.length; a++) { /* do some work here */ } 

片段#2:

 int b = 0; while (b < arr.length) { // do work b++; } 

他们看起来像是做同样的事情,对吧? 现在让我给每个代码片段添加一行代码,让我们看看会发生什么:

片段#3:

 for (int c = 0; c < arr.length; c++) { /* do some work here */ } printf("%d\n", c); 

片段#4:

 int d = 0; while (d < arr.length) { // do work d++; } printf("%d\n", d); 

所以,当我编译一个垃圾文件与这四个embedded的片段(加上一些胶有arr.length意味着什么)我得到以下错误:

 $ clang junk.c junk.c:20:17: error: use of undeclared identifier 'c' printf("%d\n", c); ^ 1 diagnostic generated. 

使用for循环,可以让你提供更多的局部性给你的虚拟计数器variables等等。这给你在重用variables名称时没有碰撞机会(尽pipe以增加潜在阴影为代价)有更大的余地。

通常,while循环和for循环之间的区别是语法而不是性能相关的。 也就是说,看起来这个问题已经被解决了Java: Java for loop vs. while循环。 性能差异?

可读性。 而从老的VB 6天开始,每当我看到我想哭的时候。

有些情况下,循环很好用。 在返回true / false的对象上调用一个函数,但在该对象内迭代一个值。

示例是C#中的DataReader:

 List<string> strings = new List<string>(); while(DataReader.Read()) { strings.Add(DataReader["foo"].ToString()); } 

一个for循环允许你在一个函数中封装你的工作,从而提供更好的内存pipe理。 另外,如果在while循环中有错误,它可能会变成一个失控的循环,威胁着所有的生命:

 bool keepGoing = true; while(keepgoing) { try { //something here that causes exception, fails to set keepGoing = false; keepGoing = false; } catch(Exception) { //Do something, but forget to set keepGoing. //maybe there is always an exception... } } 

我也认为这只是一般的做法。 就像在施工。 你用钉子把屋顶平台放到柱头上。 你“可以”使用螺丝钉,他们会做同样的工作,但这只是不常见的做法。

没有人说这是错的,我们只是说“请在同行的压力下折叠,以保持编码世界的正常运转”。

forwhile循环之间有语义上的区别。 使用for循环时,迭代次数是预先定义的,而使用while循环则没有必要。

一些语言(如Ada)通过在循环体内使for循环计数器保持不变for强制执行此操作。 因此,举例说:

 for i in values'range loop ... i := i + 1; -- this is illegal, as i is a constant within the loop body end if; 

然而,对于大多数语言来说,这种语义上的差异并不是很清楚,它们并不把for循环计数器当作一个常量。

只需决定一个,然后在整个项目中复制并粘贴/调整它。 更less的决定,更less的打字,更快的编码。 性能差异微不足道。

此外,我不与贾斯汀保持i在循环范围内,并且我也使用循环外的var aL = array.length 。 然后在for循环构造函数中使用iaL ,这样就不会重新计算每个命中的数组长度(以及反复创build的variables)。 再次否定。 性能真的(见我的答案的第一位),除非你有很大的arrays飞来飞去。 如果你碰巧知道arrays长度在前面,首先启动它的固定长度(在蹩脚的浏览器上稍微帮助一下内存分配;如果这是客户端,并且你有很多数据)。

js例子

 <script> var i=0; var myArray = ["D","R","Y"];//literal style will do for now;) var aL=myArray.length; //or use 3 if known upfront for(i;i<aL;i++){/*always do DRY things here*/} </script> 

还要确保一个条件满足时,问自己“我是否还需要完成整个循环?” 如果不是不要忘记尽早打破循环。

相关的琐事:

在Google的新Go语言中 ,他们决定不包含while语句。 相反,它们允许你写一个只有条件子句的语句。 所以相当于

 while (a < b) { ... } 

简单地说

 for a < b { ... } 

简单的说:

“for”循环往往被用于迭代使用。 你需要遍历一个数组,你需要数字1到100(或其他范围),由于各种原因。

“while”循环往往是一个条件循环。 你想继续做一些事情,直到一个错误。 假设你有一个叫做“Toast”的课程,并且你想烤面包,那么你应该有如下的东西:

while (!toast.isToasted) cook(toast);

你可以大多数情况下(我不能想到一个例子,你不能)写一个for循环作为一个while循环和一个while循环作为for循环,但select一个最好的情况通常归结为我以上几点。

可读性是非常重要的一点,但是它可以同时工作。 即使在使用计数器variables的情况下,我也会将一个for循环转换为while循环,否则,当它更具可读性时,它就会被“自然地”使用。 当你在三部分或多个计数器中有一个长或复杂的expression式时(这与复杂有关),这是常见的。

Knuth的循环与半循环在多种语言中也可以更好地工作,作为一个有中断的无限循环,而不是for循环。

但是,有一个非常重要的语义差异:

 for (int i = 0; i < arr.length; i++) { if (filter(arr[i])) continue; use(arr[i]); } int i = 0; while (i < arr.length) { if (filter(arr[i])) continue; use(arr[i]); i++; } 

适当时使用for-loop。 while解决scheme有语法上的缺点(更长),你必须检查你在循环内继续调用之前递增i。

偏爱。 对于我来说,所有的循环逻辑都内置在for语句中,所以你不必在实际的循环中声明计数器variables或者执行递增/递减的东西。 此外,您可以声明for语句的本地计数器/索引。

For循环通常更容易并行化。 由于程序可以预先知道将要执行的迭代次数和迭代器的值,所以使用诸如OpenMP的API的并行化是微不足道的。 当然,如果你进入rest,继续,手动改变迭代器,这个优势消失。

因为后者可以是一个class轮:while(++ i <arr.length){// do work}

一个原因是,一段时间的条件可以是一个string。

另外,如果我们在混合中添加“Do”,我们可以使用do while循环,而不pipe当前状态如何,至less要运行一次。

它只是我的逻辑,当我们知道我们的迭代的确切数量时,我们通常使用循环,当我们通常要检查一个条件时,我们使用一个while循环。然后根据您的需求使用它们。 否则,他们都显示相同的行为。

一个while循环,定义为

 while(condition) 

代表这种编程模式:

 1: if(!condition) goto 2; ... goto 1; 2: 

而for循环,定义为

 for(var i = seed; condition; operation) 

代表了这种模式:

 var i = seed 1: if(!condition) goto 2; ... operation; goto 1; 2: 

这两种模式都是如此普遍使用,他们已经被命名和build成语言。

如果你需要定义一个计数器来控制你的循环,使用for循环。 如果没有,请使用while循环。