为什么for和while循环里最好不要用continue和break

说好一起扑成狗 2018-04-22 08:04:11
看到王垠微博的一篇文章.
说在for,while循环里 避免使用continue和break,这样会让循环逻辑和终止条件变的复杂,难以保证正确.
出现continue/break的原因,对循环逻辑没想清楚,想清楚了就不会出现continue和break.
99%的break和continue,都可以通过替换成return语句,或者翻转if条件的方式来消除掉。
剩下的1%含有复杂的逻辑,但也可以通过提取一个帮助函数来消除掉。从而使代码变得容易理解,容易确保正确。

我自己能想到的:
for和while本身有终止条件,内部再有break和continue,使条件变多,也违背了一进一出原则,所以复杂了.
我的问题是:
1)我这样理解对吗?还有其他原因吗?最好能举例说明.
2)什么是帮助函数?最好能举个例子.

3)如果写成循环无条件执行,只在内部有终止条件,这样写好吗?如果不好,请举例子说明.
while(1)
{
...;
if(...)
{
break;
}
}

4)同样条件下,一些函数和变量写在循环内部好,还是外部好.
(写在里面,会随着循环终止,自动销毁,写在外面,如果再次引用会有不可预料的结果,当然,永远不再引用这些变量和函数,没有问题.)
例如:

int a;
while(...)
{ ...;
a=赋值;
}

while(...)
{
int a;//变量a在循环内部好
...;
a =赋值;
}
...全文
1887 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-04-24
  • 打赏
  • 举报
回复
请牢记:源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要,重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。 意思是你程序结构看上去再合理,再简洁,也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错,更方便修改,出错了更容易找到哪里出错和具体出错的原因,更容易改正错误。 试对比 图书馆(对图书的分类够结构化了吧) 和 搜索引擎(可看作是扁平化任何结构数据,仅支持全文检索) 哪个处理信息更方便、更高效。 所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。 结构越复杂,越难修改,越难除错。 有时(甚至大多数时候),看上去越合理、越简洁的代码,运行起来性能越差,出错时查找原因越难,找到出错原因后改正越费劲。 程序员要做的不是尽力避免错误,而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误,“快速的失败”远胜过“预防错误”。Fred George 前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题;他觉得前同事们应该用这些问题来问自己;实际上不管在哪里工作的开发者们都应该经常问问自己这些问题: ◆“要保证这个问题不会再出现,我该怎么做?” ◆“要想少出些Bug,我该怎么做?” ◆“要保证Bug容易被修复,我该怎么做?” ◆“要保持对变化的快速响应,我该怎么做?” ◆“要保证我的软件的运行速度,我该怎么做?” 如果大多数团队都能不时问一下自己,必定会从中得益,因为这些都是真正强而有力的问题。
zhouqunhai 2018-04-24
  • 打赏
  • 举报
回复
引用 10 楼 wlxxxz 的回复:
[quote=引用 5 楼 zhouqunhai 的回复:] 个人习惯而已
还是要有点完美主义才好啊. //这种代码我就不能接受啊. while(条件判断1) { 一堆变量; 一堆函数; if(条件判断2) { break; } } //这样就完美了. while(条件判断1 && !条件判断2) { 一堆变量; 一堆函数; } //这种你能接受吗? while(1) { 一堆变量; 一堆函数; if(条件判断) { break; } } [/quote] 所以说嘛,作为个人只要觉得codeing舒服就行
赵4老师 2018-04-23
  • 打赏
  • 举报
回复
for (A;B;C) D;
//等价于
{
 A;
 while (1) {
  if (!(B)) break;
  D;
  C;
 }
}
赵4老师 2018-04-23
  • 打赏
  • 举报
回复
为什么while循环里一定要用continue和break :
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
while (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
while (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。
  • 打赏
  • 举报
回复
引用 5 楼 zhouqunhai 的回复:
个人习惯而已
还是要有点完美主义才好啊. //这种代码我就不能接受啊. while(条件判断1) { 一堆变量; 一堆函数; if(条件判断2) { break; } } //这样就完美了. while(条件判断1 && !条件判断2) { 一堆变量; 一堆函数; } //这种你能接受吗? while(1) { 一堆变量; 一堆函数; if(条件判断) { break; } }
AlbertS 2018-04-23
  • 打赏
  • 举报
回复
我觉的存在continue和break的逻辑挺清晰的啊,可能是习惯问题,但是我不喜欢多层嵌套的if语句,往往会拿continue逻辑替换一下
  • 打赏
  • 举报
回复
引用 4 楼 ckc 的回复:
扯蛋的观点。 工程上的东西很少有这么绝对的。连最多人反对的goto都还一直保留,还有人认为可以在必要的时候使用呢。 不同的人有不同的习惯,而且工程上也经常会遇到不同的情况。 一进一出这个根本就不算什么原则,这个充其量只是一种指导意见而已,把一进一出绝对化是很荒唐的。 日常处理逻辑有的时候就是很复杂的,在单一地方判断是否循环结束,从逻辑上说肯定是可以的, 在现实中很有可能会造成逻辑极其复杂,写这种单一的很复杂逻辑算式可能跟实际业务 没有直接对应关系,难以理解,难写也难改,实践中可能造成更多的错误。 单一出口同样也是很荒唐的,没了continue和break,那就只有增加更多的if来处理, 业务逻辑稍微复杂一些就会造成if嵌套很多层,这个同样增加了出错的风险, 这种情况下适当使用break和continue,相当于化简了处理逻辑,可以减少if的层数, 让程序跟实际业务贴合紧密,这样的程序容易理解,不容易出错,业务有调整也容易修改。

while(条件判断1)
{  一堆变量;
   一堆函数;
      if(条件判断2)
    {
        break;
    }
}

//像王垠说的可以改成:
while(条件判断1 && !条件判断2)
{
   一堆变量;
   一堆函数;
}

  • 打赏
  • 举报
回复
引用 4 楼 ckc 的回复:
扯蛋的观点。 工程上的东西很少有这么绝对的。连最多人反对的goto都还一直保留,还有人认为可以在必要的时候使用呢。 不同的人有不同的习惯,而且工程上也经常会遇到不同的情况。 一进一出这个根本就不算什么原则,这个充其量只是一种指导意见而已,把一进一出绝对化是很荒唐的。 日常处理逻辑有的时候就是很复杂的,在单一地方判断是否循环结束,从逻辑上说肯定是可以的, 在现实中很有可能会造成逻辑极其复杂,写这种单一的很复杂逻辑算式可能跟实际业务 没有直接对应关系,难以理解,难写也难改,实践中可能造成更多的错误。 单一出口同样也是很荒唐的,没了continue和break,那就只有增加更多的if来处理, 业务逻辑稍微复杂一些就会造成if嵌套很多层,这个同样增加了出错的风险, 这种情况下适当使用break和continue,相当于化简了处理逻辑,可以减少if的层数, 让程序跟实际业务贴合紧密,这样的程序容易理解,不容易出错,业务有调整也容易修改。
1)一堆嵌套,一句goto,是很爽.但嵌套里的一堆变量,函数什么的...戛然而止,不做善后处理都是隐患啊. goto能不用还是不用吧. 2)业务逻辑复杂.可以把复杂的问题拆分成一个个足够简单的小问题.一步步解决.像流水线模式一样.

//这不是好代码,两个条件判断出口.
while(条件判断1)
{  一堆变量;
   一堆函数;
	  if(条件判断2)
	{
		break;
	}

//以下代码虽然可以接受,但直观感受并不好.不知道你同意我的观点吗?
while(1)
{  一堆变量;
   一堆函数;
	  if(条件判断)
	{
		break;
	}
}
自信男孩 2018-04-23
  • 打赏
  • 举报
回复
注释不一定多,注释多了说明代码可读性有问题。既然能够用代码描述清除的,为啥非要用注释去描述呢。 对于continue和break的问题,个人认为主要是一个量,不论什么循环,用continue和break多了,那么代码可读性就会有折扣。但是需要多少除了根据逻辑来意外,能减少则减少能合并则合并。 因此,continue和break还是要用,不要害怕使用,不然我们不用break,continue,我们的逻辑如何完成呢
  • 打赏
  • 举报
回复
引用 3 楼 qq_38204686 的回复:
我感觉没有绝对的事情 存在即合理 每个人编程习惯不一样吧 关键还是写注释
写注释,我也觉得很重要. 但再多的注释,也代替不了程序逻辑正确和简洁啊.
zhouqunhai 2018-04-23
  • 打赏
  • 举报
回复
个人习惯而已
ckc 2018-04-23
  • 打赏
  • 举报
回复
扯蛋的观点。 工程上的东西很少有这么绝对的。连最多人反对的goto都还一直保留,还有人认为可以在必要的时候使用呢。 不同的人有不同的习惯,而且工程上也经常会遇到不同的情况。 一进一出这个根本就不算什么原则,这个充其量只是一种指导意见而已,把一进一出绝对化是很荒唐的。 日常处理逻辑有的时候就是很复杂的,在单一地方判断是否循环结束,从逻辑上说肯定是可以的, 在现实中很有可能会造成逻辑极其复杂,写这种单一的很复杂逻辑算式可能跟实际业务 没有直接对应关系,难以理解,难写也难改,实践中可能造成更多的错误。 单一出口同样也是很荒唐的,没了continue和break,那就只有增加更多的if来处理, 业务逻辑稍微复杂一些就会造成if嵌套很多层,这个同样增加了出错的风险, 这种情况下适当使用break和continue,相当于化简了处理逻辑,可以减少if的层数, 让程序跟实际业务贴合紧密,这样的程序容易理解,不容易出错,业务有调整也容易修改。
Gahui_Liao 2018-04-23
  • 打赏
  • 举报
回复
我觉得最好不要使用的一个原因是,当你的程序在循环里出现bug的时候,调试会变得更加复杂。
  • 打赏
  • 举报
回复
引用 15 楼 DelphiGuy 的回复:
视情况用continue和break,没有最好不要用这一说。
哈哈,大神啊,我很崇拜你.我以前也用过Delphi. 你的昵称:早打大打打核战争.我一直很好奇.
  • 打赏
  • 举报
回复
好吧,不纠结了, 顺便,问个题外话,点结贴就可以分配c币了吗?
  • 打赏
  • 举报
回复
引用 7 楼 cfjtaishan 的回复:
注释不一定多,注释多了说明代码可读性有问题。既然能够用代码描述清除的,为啥非要用注释去描述呢。 对于continue和break的问题,个人认为主要是一个量,不论什么循环,用continue和break多了,那么代码可读性就会有折扣。但是需要多少除了根据逻辑来意外,能减少则减少能合并则合并。 因此,continue和break还是要用,不要害怕使用,不然我们不用break,continue,我们的逻辑如何完成呢
//这种代码你会写吗,能接受吗? while(1) { 一堆变量; 一堆函数; if(条件判断) { break; } }
引用 12 楼 zhao4zhong1 的回复:
为什么while循环里一定要用continue和break :
不要使用
while (条件)
更不要使用
while (组合条件)
要使用
while (1) {
 if (条件1) break;
 //...
 if (条件2) continue;
 //...
 if (条件3) return;
 //...
}
因为前两种写法在语言表达意思的层面上有二义性,只有第三种才忠实反映了程序流的实际情况。
典型如:
下面两段的语义都是当文件未结束时读字符
while (!feof(f)) {
 a=fgetc(f);
 //...
 b=fgetc(f);//可能此时已经feof了!
 //...
}
而这样写就没有问题:
while (1) {
 a=fgetc(f);
 if (feof(f)) break;
 //...
 b=fgetc(f);
 if (feof(f)) break;
 //...
}
类似的例子还可以举很多。
赵老师就是赵老师,一语点醒梦中人. 赵老师我还看过你的视频呢,嘿嘿.
小灰狼 2018-04-23
  • 打赏
  • 举报
回复
确实很扯淡的规定 我就喜欢在for/while里写continue/break/,甚至是 return。有时能起到简化的效果 程序结构是否复杂,不是看你是否用了 continue/break,而是程序员写程序时的思维。如果不顾一切地乱写一气,不用 break/continue,也一样乱
l357630798 2018-04-23
  • 打赏
  • 举报
回复
引用 4 楼 ckc 的回复:
扯蛋的观点。 工程上的东西很少有这么绝对的。连最多人反对的goto都还一直保留,还有人认为可以在必要的时候使用呢。 不同的人有不同的习惯,而且工程上也经常会遇到不同的情况。 一进一出这个根本就不算什么原则,这个充其量只是一种指导意见而已,把一进一出绝对化是很荒唐的。 日常处理逻辑有的时候就是很复杂的,在单一地方判断是否循环结束,从逻辑上说肯定是可以的, 在现实中很有可能会造成逻辑极其复杂,写这种单一的很复杂逻辑算式可能跟实际业务 没有直接对应关系,难以理解,难写也难改,实践中可能造成更多的错误。 单一出口同样也是很荒唐的,没了continue和break,那就只有增加更多的if来处理, 业务逻辑稍微复杂一些就会造成if嵌套很多层,这个同样增加了出错的风险, 这种情况下适当使用break和continue,相当于化简了处理逻辑,可以减少if的层数, 让程序跟实际业务贴合紧密,这样的程序容易理解,不容易出错,业务有调整也容易修改。
顶~
donjin9 2018-04-23
  • 打赏
  • 举报
回复
代码的可读性是很重要的。 用if消除break和continue,可能更复杂,各种状态或嵌套。 习惯用 for (;;) { if () break; if () continue; }
  • 打赏
  • 举报
回复
视情况用continue和break,没有最好不要用这一说。
加载更多回复(4)

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧