控制循环(P367)
1.选择循环的种类(P367)
- 记数循环
- 连续求值的循环
- 无限循环
- 迭代器循环
1)什么时候用while循环
如果你预先不知道循环要迭代多少次,那么就使用while循环
2)什么时候用带退出的循环
带退出的循环也是单入单出的结构化控制结构,也是一种首选的循环控制。
3)何时用for循环
如果你需要一个执行次数固定的循环,那么for循环就是一个很好的选择。
4)何时用foreach循环
foreach循环或其等价物很适用于对数组或者其他容器各项元素执行操作。
2.循环控制(P373)
循环会出什么样的错误呢:忽略或错误地对循环执行初始化、忽略了对累加变量或其他与循环有关的变量执行初始化、不正确的嵌套、不正确的循环终止、忽略或者错误地增加了循环变量的值、以及不正确的循环下标访问数组元素等。你可以采取两种方法来阻止这些错误的发生。首先,减少能影响该循环各种因素的数量。其次,把循环内部当做一个子程序看待——把控制尽可能地放到循环体外。把循环体执行的条件表述清楚。不要让读者看了循环体以后才明白循环的控制。应该把循环看做是一个黑盒子:外围程序只知道它的控制条件,却不知道它的内容。while( !inputFile.EndOfFIle() && moreDataAvailable){ ************************************ * * * 黑盒子 * * * ************************************ }
1)进入循环
- 只从一个位置进入循环
- 把初始化代码紧放在循环前面
- 用while(true)表示无限循环
- 在适当的情况下多使用for循环
- 在while循环更适用的时候,不要使用for循环
2)处理好循环体
- 用“{”和“}”把循环中的语句括起来
- 避免空循环
- 把循环内务操作要么放在循环的开始,要么放在循环的末尾
循环内务操作是指像i=i+1或者j++这样的表达式- 一个循环只做一件事
3)退出循环
- 设法确认循环能够终止
- 使循环终止条件看起来很明显
- 不要为了终止循环而胡乱改动for循环的下标
- 避免出现依赖于循环下标最终取值的代码
- 考虑使用安全计数器
safetyCounter = 0; do{ node = node->next; ... safetyCounter++; if(safetyCounter >= SAFETY_LIMIT){ Assert( false, "INternal Error: Safety-Counter Violation."); } ... }while( node->Next != NULL);
- 考虑在while循环中使用break语句而不用布尔标记
- 小心那些有很多break散布其中的循环
- 在循环开始处使用continue进行判断
- 如果语言支持,请使用带标号break结构
do{ ... switch ... CALL_CENTER_DOWN: if(){ ... break CALL_CENTER_DOWN; ... } ... }while(...);
- 使用break和continue时要小心谨慎
4)检查端点
对于一个简单循环,通常需要注意三种情况:开始的情况,任意选择的中间情况,以及最终的情况。在你创建循环的时候,应在脑海里运行这三种循环的情况,以确认该循环不会出现任何off-by-one错误。是否愿意执行这种检查,是高效程序员和低效程序员之间的一项关键差别。
5)使用循环变量
- 用整数或者枚举类型表示数组和循环的边界
而不是浮点数据- 在嵌套循环中使用有意义的便利名来提高其可读性
- 用有意义的名字来避免下标串话
- 把循环下标变量的作用域限制在本循环内
6)循环应该有多长
- 循环要尽可能地短,以便能够一目了然
- 把嵌套限制在3层以内
- 把长循环的内容移到子程序里
- 要让长循环格外清晰
3.轻松创建循环——由内而外(P385)
假如你正在为一家保险公司开发程序。其中的寿险费要根据人员年龄的性别的不同而变化。你的职责是开发一个能够计算一组人员的人寿保险费用总额的子程序。需要写一个能够从列表中取得每个人的费率并能进行累加的循环。你应该像下面这样做。/** * 第1步:由内而外创建循环(伪代码示例) */ --get rate from table --add rate to total
/** * 第2步:由内而外创建循环(伪代码示例) */ rate = table[] //还没任何下标的table totalRate = totalRate + rate
/** * 第3步:由内而外创建循环(伪代码示例) */ rate = table[ census.Age][census.Gender] totalRate = totalRate + rate
/** * 第4步:由内而外创建循环(伪代码示例) */ for person = firstPerson to lastPerson rate = table[ census.Age, census.Gender] totalRate = totalRate + rate
/** * 第5步:由内而外创建循环(伪代码示例) */ for person = firstPerson to lastPerson rate = table[ census[ person].Age, census[ person].Gender] totalRate = totalRate + rate
/** * 最后一步:由内而外创建循环(伪代码示例) */ totalRate = 0; for person = firstPerson to lastPerson rate = table[ census[ person].Age, census[ person].Gender] totalRate = totalRate + rate
4.循环和数组的关系(P387)
循环和数组之间有着密切的联系。在许多情况中,循环就是用来操纵数组的,而且循环计数器和数组下标一一对应。