为什么使用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!=EOF
,diff<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... } }
我也认为这只是一般的做法。 就像在施工。 你用钉子把屋顶平台放到柱头上。 你“可以”使用螺丝钉,他们会做同样的工作,但这只是不常见的做法。
没有人说这是错的,我们只是说“请在同行的压力下折叠,以保持编码世界的正常运转”。
for
和while
循环之间有语义上的区别。 使用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
循环构造函数中使用i
和aL
,这样就不会重新计算每个命中的数组长度(以及反复创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循环。