编程语言可以很迅速方便地帮我们完成一些重复性的任务,从多个基本计算到几乎完成了很多类似工作的其他情况。现在, 我们看看君土脚本如何用循环结构来处理这种需求。
来, 一起循环
循环,循环,循环。一年四季往复, 音乐一遍又一遍播放和重复生产一个又一个的产品,与这些一样, 类似的情况存在于编程中。编程中的循环也是一直重复着去做一件事 – 此处循环便是编程中的术语.
让我们来想想下图,这位家长考虑为他的家庭做一周的食物计划,他或许就需要执行一段循环:
一段循环通常需要一个或多个条件:
- 一个开始条件,它被初始化为一个特定的值 – 这是循环的起点(“开始:我没有食物”,上面的例子)。
- 一个结束条件,这是循环停止的标准 – 通常计数器达到一定值。 以上所说的“我有足够的食物”吗? 假设他需要10份食物来养活他的家人。
- 一个迭代器,这通常在每个连续循环上递增少量的计数器,直到达到退出条件。 我们以前没有明确说明,但是我们可以考虑一下成人能够每小时收集2份食物。 一小时后,他收集的食物量增加了两份,他检查他是否有足够的食物。 如果他已经达到10分(退出条件),他可以停止收集, 然后回家。
在伪代码中,这看起来就像下面这样:
循环(食物 = 0; 需要的食物 = 10) { 若 (食物 = 需要的食物) { 离开 循环; // 我们有足够的食物了,回家吧。 } 别 { 食物 += 2; // 花一个小时多收集两个食物。 // 循环将会继续执行。 } }
所以需要的食物量定为10,家里目前有的数量为0。在循环的每次迭代中,我们检查家里的食物量是否等于他需要的量。 如果等于,我们可以退出循环。 如果小于,成人花一个小时收集两份食物,循环再次运行。
为何用循环?
在这一点上,您可能会了解循环中的高级概念,但您可能会认为“好的,但是,这有助于我编写更好的君土脚本代码?” 正如我们前面所说,循环所做的事情都是一样的,这对于快速完成重复任务是非常有用的。
通常,循环的每个连续迭代的代码将略有不同,这意味着您可以完成非常相似但略有区别的任务; 例如, 有很多不同的数需要计算,我们用同一种方式去计算这些数, 不是每一个数用不同的方式计算!
让我们来看一个例子来说明为什么循环是一件好事。 假设我们想在终端上
打印10行随机数量的星号(:
* ***** **** * **** *** *** **** *** ****** ******
您现在不需要理解所有代码,但我们来看看这些代码:
务 随机数(最大: 数): 数 {
回 算.顶(算.随机() * 最大)
}
务 绘制星号() {
常 打印行数 = 10;
常 每行最多星数 = 15;
为 (定 甲 = 0; 甲 < 打印行数; 甲++) {
定 星数 = 随机数(每行最多星数);
为 (定 乙 = 0; 乙 < 星数; 乙++) {
进程.输出.写('*');
}
进程.输出.写("\n");
}
}
绘制星号();
随机数()
,我们编写的函数,它返回一个0
到最大-1
间的整数。
您应该有一个基本的想法 – 我们使用两个循环嵌套来运行这个代码的迭代。 无论我们打印10行,1000还是10,000,所需的代码量将是相同的。 只有一个数字必须改变。
如果我们在这里没有使用循环,我们必须为我们想要打印重复以下代码:
进程.输出.写('*\n');
进程.输出.写('**\n');
......
这将非常无聊而且很难维持高速。 循环真的相当好用。
循环的标准
我们开始探索一些特定的循环结构。 第一个,你会经常使用到它,为/*for*/
循环 – 以下是为
循环的语法:
为 (初始化器; 退出条件; 最后表达式) { // 运行这里的代码 }
我们有:
- 关键字
为
,后跟一个括号。 - 在括号内,我们有三个项目,以分号分隔:
- 一个初始化器 – 这通常是一个设置为一个数字的变量,它被递增来计算循环运行的次数。它也有时被称为计数变量。
- 一个退出条件 -如前面提到的,这个定义循环何时停止循环。这通常是一个表现为比较运算符的表达式,用于查看退出条件是否已满足的测试。
- 一个最后表达式 – 每次循环经过完整的迭代时,都会对其进行计算(或运行)。它通常用于增加(或在某些情况下减少)计数器变量,使其更接近退出条件值。
- 一个包含代码块的花括号 – 每次循环迭代时都会运行这个代码。
让我们看一个真实的例子,这样我们可以更清楚地想象它们的作用。
定 课程 = ['君土脚本编程入门', '超文本入门', '样式表入门', '数据结构', '软件工程'];
定 信息 = '我要学习的课程有';
为 (定 甲 = 0; 甲 < 课程.长; 甲++) {
信息 += 课程[甲] + ', ';
}
控制台.日志(信息);
这将给我们以下输出:
我要学习的课程有君土脚本编程入门, 超文本入门, 样式表入门, 数据结构, 软件工程,
这显示了一个循环用于迭代数组中的项,并对每个项执行一些操作——这是君土脚本中非常常见的模式。 这里:
- 迭代器
甲
从0开始(定 甲 = 0
)。 - 循环被告知一直运行到
甲
不再小于课程
数组的长度为止。这一点很重要——退出条件是循环仍然运行的条件。在这个例子中,当甲 < 课程.长
仍然为真,循环仍然会运行。 - 在循环中,我们将当前的循环项(
课程[甲]
是课程[当前下标的任何东西]
)以及逗号和空格连接到信息
变量的末尾。 所以:- 在第一次运行中,甲
= 0
,所以课程[0] +','
(课程[0]的值是”君土脚本编程入门”) 将被连接到信息
上。 - 在第二次运行中,甲
= 1
,所以课程[1] +','
(课程[1]的值是”超文本入门”) 将被连接到信息
上。 - 等等。 每次循环运行后,1将被添加到甲(甲 ++),然后流程将再次启动。
- 在第一次运行中,甲
- 当等于
课程.长
时,循环将停止,代码运行将移动到循环下面的下一个代码位。
注意: 我们将退出条件设为甲 < 课程.长
,而不是甲 <= 课程.长
,因为计算机从0开始计数,而不是1——我们从0开始,一直到甲 = 4
(最后一个数组项的下标)。课程.长
返回5, 数组中有5个项目, 我们不希望达到甲 = 5
, 因为这将返回未定义的最后一个项目(没有索引为5的数组项目)。所以我们想要比课程.长少1(甲 < 课程.长
),而不是课程.长(甲 <= 课程.长
)。
注意: 退出条件的一个常见错误是使它们使用“等于”(===
)而不是说“小于或等于”(<
)。 如果我们想要运行我的循环到甲 = 4
,退出条件将需要是甲 < 课程.长
。如果我们设置为甲 === 课程.长 -1
,循环将不会运行,因为在第一次循环迭代时 甲 不等于4
,所以循环会立即停止。
我们留下的一个小问题是最后的输出句子形式不是很好:
我要学习的课程有君土脚本编程入门, 超文本入门, 样式表入门, 数据结构, 软件工程,
理想情况下,我们想改变最后循环迭代中的拼接,以便在句子末尾没有逗号。 嗯,没问题 – 我们可以很高兴地在我们的为
循环中插入一个条件来处理这种特殊情况:
为 (定 甲 = 0; 甲 < 课程.长; 甲++) {
若 (甲 === 课程.长 - 1) {
信息 += '和' + 课程[甲] + '。';
} 别 {
信息 += 课程[甲] + ', ';
}
}
警告:对于为
循环——就像所有循环一样——你必须确保初始化器是递增的,或者是递减的(取决于具体情况),这样它最终会到达条件不为真的点。如果没有,循环将永远继续下去,运行环境将迫使它停止,或者它将崩溃。这被称为无限循环。
使用断退出循环
如果要在所有迭代完成之前退出循环,可以使用 断/*break*/
语句。 当我们学习 支
语句时,我们已经在上一篇文章中遇到过这样的情况 – 当 支
语句中符合输入表达式的情况满足时,断
语句立即退出 支
语句并移动到代码之后。
循环中也相同 – 断
语句将立即退出循环,并执行跟随它的任何代码。
说我们想搜索一系列联系人和电话号码,只返回我们想要找的号码?
定 联系人 = ['张三:2232322', '李四:3453456', '王五:7654322', '赵六:9998769', '孙七:9384975'];
务 查找(查找名字: 文) {
为 (定 甲 = 0; 甲 < 联系人.长; 甲++) {
定 联系人分解 = 联系人[甲].分(':');
若 (联系人分解[0] === 查找名字) {
控制台.日志(联系人分解[0] + '的号码是' + 联系人分解[1] + '。');
断;
} 别 若 (甲 === 联系人.长 - 1) {
控制台.日志('没有找到联系人');
}
}
}
查找('张三');
查找('周八');
- 首先我们有一些变量定义 – 我们有一个联系信息数组,每个项目是一个字符串,包含一个以冒号分隔的名字和电话号码。
- 接下来,我们定义一个函数
查找
,参数为查找名字
。 - 现在是有趣的部分,
为
循环:- 我们的计数器开始时为0,直到计数器不再小于
联系人.长
,并在循环的每次迭代之后将甲递增1。 - 在循环中,我们首先将当前联系人(
联系人 [甲]
)用冒号字符拆分,并将生成的两个值存储在名为联系人分解
的数组中。 - 然后,我们使用条件语句来测试
联系人分解[0]
(联系人名字)是否等于输入的查找名字
。 如果是,我们显示一个字符串来报告联系人的号码,并使用断
来结束循环。
- 我们的计数器开始时为0,直到计数器不再小于
- 在
(联系人.长 - 1)
次迭代后,如果联系人姓名与输入的搜索不符,则显示“未找到联系人”,循环继续迭代, 结束。
使用续跳过迭代
续/*continue*/
语句以类似断的方式工作,但不是完全跳出循环,而是跳过当前迭代, 执行下一个迭代。 我们来看另外一个例子,它把一个数字作为一个输入,只返回小于等于这个数字并且开平方之后为整数的数字(整数)。
务 平方数(输入数:数) {
定 输出信息 = '';
为 (定 甲 = 1; 甲 <= 输入数; 甲++) {
定 平方根 = 算.方根(甲);
若 (算.底(平方根) !== 平方根) {
续;
}
输出信息 += 甲 + ' ';
}
控制台.日志(输出信息);
}
平方数(1);
平方数(20);
平方数(100);
这是输出:
1 1 4 9 16 1 4 9 16 25 36 49 64 81 100
为
循环给定一个从1开始的计数器(在这种情况下,我们对0不感兴趣),一个退出条件,当计数器大于输入输入数
时循环将停止,并且迭代器的计数器将每次增加1。- 在循环中,我们使用
算.方根(甲)
找到每个数字的平方根,然后测试平方根是否是一个整数,通过判断当它被向下取整时,它是否与自身相同(这是算.底(...)
对传递的数字的作用)。 - 如果平方根和平方根向下取整的不相等(
!==
),则表示平方根不是整数,因此我们对此不感兴趣。 在这种情况下,我们使用续
语句跳过当前循环而执行下一个循环迭代,而不在任何地方记录该数字。 - 如果平方根是一个整数,我们完全跳过
若
块,所以续
语句不被执行; 相反,我们将当前甲
值加上一个空格连接到输出信息
的末尾。
复语句和行复语句
为
不是君土脚本中唯一可用的循环类型。 实际上还有很多其他的,虽然你现在不需要了解所有这些,但有必要看看其他几个的结构,这样你就可以在稍微不同的方式中识别出相同的功能。
首先,我们来看看 复/*while*/
循环。 这个循环的语法如下所示:
初始化器 复 (退出条件) { // 运行这里的代码 最后表达式 }
除了在循环之前设置初始化器变量,并且在运行代码之后,循环中包含 最后表达式 ,而不是这两个项目被包含在括号中,这与以前的为
循环非常类似。 退出条件包含在括号内,前面是复
关键字而不是为
。
同样的三个项目仍然存在,它们仍然以与为
循环中相同的顺序定义 – 这是有道理的,因为您必须先定义一个初始化器,然后才能检查它是否已到达退出条件; 在循环中的代码运行(迭代已经完成)之后,运行最后的条件, 再次检查它是否已到达退出条件。
我们再来看看我们的课程列表示例,但是重写了一个复
循环:
定 甲 = 0;
复 (甲 < 课程.长) {
若 (甲 === 课程.长 - 1) {
信息 += '和' + 课程[甲] + '。';
} 别 {
信息 += 课程[甲] + ', ';
}
甲++;
}
注意: 它正如我们期望的那样工作。
行/*do*/...复/*while*/
循环与非常复
类似, 但提供了复
结构的一个变体:
初始化器 行 { // 运行这里的代码 最后表达式 } 复 (退出条件)
在这种情况下,在循环开始之前,初始化器
先重新开始。 行
关键字直接在包含要运行代码的花括号和终止条件之前。
这里的区别在于,条件出现在其他内容之后,用圆括号括起来,前面有一个复
关键字。 在 行 ... 复
循环中,花括号中的代码总是在检查之前运行一次,以查看是否应该再次执行(在复
和为
中,检查首先出现,因此代码可能永远不会执行)。
我们再次重写我们的课程列表示例,以使用行...复
循环:
定 甲 = 0;
行 {
若 (甲 === 课程.长 - 1) {
信息 += '和' + 课程[甲] + '。';
} 别 {
信息 += 课程[甲] + ', ';
}
甲++;
} 复 (甲 < 课程.长);
注意: 再一次,它正如我们期望的那样工作。
重要: 使用 复
和 行...复
— 所有循环都一样 — 你必须保证初始变量是迭代的,那么它才会逐渐地达到退出条件。不然,它将会永远循环下去, 要么系统强制终止它,要么它自己会崩溃. 这称为无限循环.
应该使用哪种循环类型?
对于基本用途,为
,复
和行复
循环大部分可互换。 他们都可以用来解决相同的问题,你使用哪一个将在很大程度上取决于你的个人偏好 – 哪一个你最容易记住或是最直观的。 我们再来看看他们。
首先是 为
:
为 (初始化器; 退出条件; 最后表达式) { // 运行这里的代码 }
复
:
初始化器 复 (退出条件) { // 运行这里的代码 最后表达式 }
最后是 行...复
:
初始化器 行 { // 运行这里的代码 最后表达式 } 复 (退出条件)
我们建议使用为
,因为它可能是最简单地帮你记住一切 – 初始化程序,退出条件和最后表达式都必须整齐地放入括号,所以很容易看到他们在哪里并检查你没有丢失他们。
注:还有其他循环类型/特性,这些特性在 高级/专门 的情况下是有用的,超出了本文的范围。如果您想进一步了解循环学习,请阅读我们的高级循环和迭代指南。
结论
本文向您展示了君土脚本循环代码背后的基本概念和不同的选项。现在您应该清楚为什么循环是处理重复代码的好机制,并渴望在您自己的例子中使用它们!
如果您有什么不明白的地方,可以再通读一遍,或者联系我们寻求帮助。