很多教程把易语言的循环命令放在最后一章讲,但实际写工具时,循环往往是整个程序跑起来的关键。尤其是“循环判断首”和“判断循环首”这两个命令,名字只换了两个字的顺序,很多新手第一次用都会拿混。我在给某个工具加自动重试逻辑时,就用错过一次:本来该“先执行一次再判断”的地方,我写成了“先判断再执行”,结果初始化步骤直接跳过,后面数据全乱了。那次以后我认真把易语言的这两组循环流程控制命令捋了一遍,才发现只要把执行顺序想清楚,它们一点都不难。这篇文章就把“循环判断首”和“判断循环首”的语法、区别、常见坑和选型思路一次性说透,易语言入门的朋友可以直接照着抄。
1. 先搞清楚:易语言里的循环流程控制到底在控制什么
1.1 循环结构的四个基本要素
不管用哪种语言写循环,本质上都绕不开四件事:初始状态、进入条件、循环体、状态更新。易语言把这四件事拆成了不同的命令,而不是像某些语言那样给你一个统一的for或while。这个设计对中文用户很友好,但也带来一个副作用:命令名字太多,初学者容易记混。
在标题里提到的“循环判断首”和“判断循环首”,对应的正是两种最常见的条件循环:
- 判断循环首:先判断条件,条件为真才进入循环体。
- 循环判断首:先执行一次循环体,再判断条件,决定是否继续。
一个是“进门之前先看牌子”,一个是“先进门再说”。这个比喻我后面会反复用,因为它能直接解决绝大多数选择困难。
1.2 易语言的循环命令家族
易语言里循环相关的命令不止这两个,完整看的话有四组:
| 命令对 | 执行方式 | 典型场景 |
|---|---|---|
| 计次循环首 / 计次循环尾 | 固定循环次数,用一个隐藏计数器自动计数 | 已知循环 n 次,比如遍历数组 |
| 变量循环首 / 变量循环尾 | 使用指定变量作为计数器,支持步长 | 从 1 循环到 100,每次加 2 |
| 判断循环首 / 判断循环尾 | 先判断条件,满足则执行循环体 | 条件未知,但需要“满足时继续” |
| 循环判断首 / 循环判断尾 | 先执行循环体,再判断条件 | 至少执行一次,再看条件决定是否继续 |
标题里的两个命令属于后两组。它们解决的核心问题不是“循环几次”,而是“循环到什么时候为止”。换句话说,它们处理的是条件判断和循环体之间的先后关系。
我第一次接触易语言时,以为“循环判断首”和“判断循环首”只是一个命令的两种写法,后来写了几个测试程序才发现,它们的共同点只是“都有首尾两个命令”,但条件放在哪个位置,决定了整个流程的走向。
2. 判断循环首:先看条件再进门
2.1 语法拆解
判断循环首的完整写法是:
判断循环首 (判断条件) 循环体 判断循环尾 ()执行顺序非常直白:先判断“判断条件”,如果条件是“真”,就执行下面的循环体;执行完一遍之后,再次回到判断循环首,重新判断条件;直到某次判断条件为“假”,程序跳出循环,继续执行判断循环尾后面的代码。
这相当于其他语言里的while循环。最典型的特征就是:如果第一次判断条件就是假,循环体一次都不会执行。
2.2 最小示例:从 1 加到 100
我写程序时喜欢先跑一个 10 秒能看到结果的小例子,避免直接上大逻辑。下面这个例子就是用判断循环首求 1 到 100 的和:
.版本 2 .支持库 spec .程序集 窗口程序集_启动窗口 .子程序 _按钮1_被单击 .局部变量 计数器, 整数型 .局部变量 总和, 整数型 计数器 = 1 总和 = 0 判断循环首 (计数器 ≤ 100) 总和 = 总和 + 计数器 计数器 = 计数器 + 1 判断循环尾 () 调试输出 (总和)这段代码里,计数器先被赋值为 1。进入判断循环首后,判断计数器 ≤ 100是否为真。因为 1 确实小于等于 100,所以进入循环体,把计数器的值累加到总和里,然后计数器加 1。循环执行 100 次之后,计数器变成 101,条件不成立,循环停止。
这里有一个非常容易被忽略的点:循环体里必须有“计数器 = 计数器 + 1”这样的状态更新语句。一旦漏掉,计数器永远是 1,条件永远成立,程序就会陷入死循环。我见过不少朋友第一次写这个例子,信息框蹦个不停,只能强制结束程序,就是因为忘了更新计数器。
2.3 判断循环首的适用场景
判断循环首最擅长处理“不知道要循环多少次,但知道什么条件下需要继续”的情况。比如:
- 循环读取数据,直到读到空值为止。
- 循环等待某个全局标志位变成假。
- 循环轮询窗口是否已经被关闭。
以等待窗口关闭为例,可以这样写:
判断循环首 (窗口是否存活 (目标句柄)) 延时 (500) 处理事件 () 判断循环尾 ()这个模式在写辅助工具或自动化脚本时非常常用。每次循环先判断窗口是否还活着,活着就等半秒继续;窗口没了,条件变成假,循环自动退出。
3. 循环判断首:先进门再看条件
3.1 语法拆解
循环判断首的完整写法是:
循环判断首 () 循环体 循环判断尾 (判断条件)注意条件的位置变了。条件不在首部,而在尾部“循环判断尾”那里。程序执行时,会直接先进入循环体,执行一次完整的循环体代码,然后再走到循环判断尾,判断条件是否为真。如果条件为真,就跳回循环判断首继续执行;如果条件为假,就结束循环。
这相当于其他语言里的do...while循环。它的最大特征就是:循环体至少会执行一次。即使条件一开始就是假,也无法阻止第一轮循环体运行。
3.2 最小示例:输出 1 到 5
.版本 2 .支持库 spec .程序集 窗口程序集_启动窗口 .子程序 _按钮1_被单击 .局部变量 计数器, 整数型 计数器 = 0 循环判断首 () 计数器 = 计数器 + 1 调试输出 (计数器) 循环判断尾 (计数器 < 5)这段代码运行后,调试输出会依次显示 1、2、3、4、5。过程是这样的:
- 第一次进入循环判断首,计数器先变成 1,然后输出 1。
- 走到循环判断尾,判断
1 < 5为真,继续循环。 - 第二次进入,计数器变成 2,输出 2。
- 直到计数器变成 5,输出 5 之后,判断
5 < 5为假,循环结束。
如果我把计数器初始值改成 5,再运行一次,你会发现它依然会输出一个 5。这就是“至少执行一次”的直观体现。很多人在第一次学的时候会在这里绕晕:明明条件不满足,为什么还输出了一次?原因就是条件判断被放在了循环体后面。
3.3 循环判断首的最佳实践场景
循环判断首最适合“先做一次操作,再决定是否继续”的场景。最典型的是:
- 向服务器发送一条请求,接收返回值后判断是否重试。
- 读文件时先读取一行,再判断这一行是不是空行。
- 界面输入框里读取内容,判断内容是否合法,不合法就重新弹窗让用户输入。
以登录重试为例,登录逻辑往往需要先尝试一次,如果登录失败,再反复重试:
.局部变量 登录成功, 逻辑型 登录成功 = 假 循环判断首 () 登录成功 = 尝试登录 (编辑框账号.内容, 编辑框密码.内容) 如果真 (登录成功 = 假) 信息框 (“账号或密码错误,请重试”, 0, , ) 延时 (1000) 如果真结束 循环判断尾 (登录成功 = 假)因为第一次登录的结果至少要知道,所以这里用循环判断首比判断循环首更合适。如果用判断循环首,初始先判断登录成功 = 假,虽然也会进入,但逻辑上多绕了一层,容易写混。
4. 循环体里如何提前退出:跳出循环和到循环尾
4.1 跳出循环
不管用判断循环首还是循环判断首,循环体内部都可能出现“条件还没到,但已经可以结束”的情况。这时候就需要“跳出循环”命令。
判断循环首 (真) 如果真 (某个条件成立) 跳出循环 () 如果真结束 判断循环尾 ()跳出循环会直接终止整个循环,不管后面的条件是什么。它对应其他语言的break。最常见的用法是在死循环里做“达到预期结果就停止”的判断。
我写一个查找数组元素的例子:
.局部变量 i, 整数型 .局部变量 找到位置, 整数型 找到位置 = -1 i = 1 判断循环首 (i ≤ 取数组成员数 (数组)) 如果真 (数组 [i] = 目标值) 找到位置 = i 跳出循环 () 如果真结束 i = i + 1 判断循环尾 ()找到目标值后立刻跳出,避免继续遍历剩下的数据,省时间也省性能。这里的“跳出循环”动作在循环判断首里同样适用。
4.2 到循环尾
“到循环尾”则是另一个动作:跳过本次循环体中剩下的代码,直接回到循环尾继续判断条件。它对应其他语言的continue。
在循环里,如果某个数据不满足处理要求,可以先跳过,不终止整个循环。比如只统计数组中大于 0 的数:
判断循环首 (i ≤ 取数组成员数 (数组)) 如果真 (数组 [i] < 0) 到循环尾 () 如果真结束 正数个数 = 正数个数 + 1 i = i + 1 判断循环尾 ()由于“到循环尾”会直接跳到循环尾,后面的i = i + 1也会被跳过。因此这种写法有隐患:如果某个负数让i没增加,下一次循环会卡在同一个下标上。正确的做法是把i = i + 1放在循环体的最前面,或者用变量循环首。
4.3 和“返回”的区别
很多初学者会把“跳出循环”“到循环尾”和“返回”混在一起。它们的区别其实很明显:
- 跳出循环:结束当前这一层循环。
- 到循环尾:结束当前这一轮循环体,进入下一次循环判断。
- 返回:直接退出整个子程序,后面的代码不再执行。
如果程序正在一个子程序里执行循环,遇到“返回”命令,不只是循环停了,整个子程序都停了。所以需要先想清楚:你是想退出循环,还是想退出整个函数?我用易语言时经常在子程序里提前返回,如果外层还有资源需要释放,就得注意返回前处理干净。
5. 选错循环会踩的坑:从卡死到漏数据
5.1 死循环:条件永远不更新
这是所有循环命令共用的坑。判断循环首的条件如果是一个恒真的值,循环体里又没有跳出循环,程序就会卡死。
举一个反面例子:
.局部变量 标志, 逻辑型 标志 = 真 判断循环首 (标志) 延时 (100) 处理事件 () 标志 = 假 ' 这句被注释掉了 判断循环尾 ()如果标志 = 假被注释掉,条件永远是真,循环永远不会停。主窗口可能看起来没反应,程序占用 CPU 飙升。解决办法就是在循环体里给条件变量赋新值,或者用“跳出循环”主动结束。
5.2 初始条件判断导致一次都不执行
判断循环首的最大特点是“先判断后执行”。如果初始条件不满足,整个循环体一次都不会跑。这在很多业务逻辑里会导致“漏执行”问题。
比如读取一个文件,第一行就有内容,但文件指针初始状态可能为空。如果写成判断循环首(“读出来的一行 ≠ 空文本”),第一次读之前还没有赋值,条件就可能是假,循环直接跳过,后面内容全部读不到。正确处理是改成循环判断首,先读一行,再判断是否为空。
循环判断首 () 当前行 = 读入一行 (文件句柄) 如果真 (当前行 = 空文本) 跳出循环 () 如果真结束 处理当前行 (当前行) 循环判断尾 (真)这里我在循环判断首内部又用了跳出循环做真正的退出判断,相当于把“先执行后判断”和“中途退出”组合起来,可控性更强。
5.3 先执行带来的多余副作用
反过来,循环判断首因为“至少执行一次”,也可能带来多余副作用。比如登录锁定机制,连续输错五次密码就锁定账号。如果用循环判断首,假设初始条件已经判定用户输错三次,程序仍然会先执行一次登录尝试,然后才判断条件。这个多余执行有可能让用户多一次错误机会。
因此,选循环判断首的前提一定是:“即使条件不满足,这次执行也是安全的,不会产生不可逆副作用。”如果循环体里有写数据库、发消息、扣款这类敏感操作,就要更加小心。
5.4 排查循环问题的方法
遇到循环不执行或死循环,我一般按这个顺序排查:
- 看条件放在哪里:判断循环尾里面还是外面?
- 看初始条件是否满足:初始条件为假,判断循环首不会执行。
- 看循环体里是否有更新条件的代码。
- 看是否有跳出循环或到循环尾干扰流程。
把上面几个问题逐一检查,循环问题基本都能定位。
6. 什么时候用计次循环和变量循环更合适
6.1 四种循环对比
标题中的两个命令更适合“不固定次数”的条件循环,但易语言还有固定次数循环的命令。有时候用错了命令,代码会写得非常别扭。
| 命令 | 判断方式 | 最少执行次数 | 适用场景 |
|---|---|---|---|
| 计次循环首/尾 | 按次数 | 0 次 | 明确知道循环 n 次 |
| 变量循环首/尾 | 按变量值范围 | 0 次 | 需要带步长的计数循环 |
| 判断循环首/尾 | 先判断条件 | 0 次 | 条件满足继续,不满足停止 |
| 循环判断首/尾 | 后判断条件 | 1 次 | 至少执行一次,再决定是否继续 |
6.2 我的选型经验
我平时选循环的顺序是这样的:
- 如果循环次数固定,直接用计次循环首,它自带计数器,不需要手动维护变量。
- 如果循环次数需要带步长,比如每隔 2 个数取一个,用变量循环首。
- 如果不知道循环次数,但知道“只要条件成立就继续”,用判断循环首。
- 如果无论条件怎样,都必须至少执行一次,用循环判断首。
举个例子,遍历一个数组求和,数组元素个数已知,那就用计次循环首:
计次循环首 (取数组成员数 (数组), i) 总和 = 总和 + 数组 [i] 计次循环尾 ()在这个例子里,计数器 i 由命令自动处理,不需要手动写i = i + 1,也不容易漏。而判断循环首和循环判断首的优势在于条件更灵活,可以结合复杂逻辑。
7. 把两个循环命令组合起来的小案例
7.1 循环处理文本行
假设要逐行读取一个文本文件,处理到某个关键词就停止。这个场景最适合“循环判断首 + 跳出循环”的组合:
.局部变量 文件句柄, 整数型 .局部变量 当前行, 文本型 .局部变量 行号, 整数型 文件句柄 = 打开文件 (“配置.ini”, 1, ) 行号 = 0 循环判断首 () 当前行 = 读入一行 (文件句柄) 如果真 (当前行 = 空文本) 跳出循环 () 如果真结束 行号 = 行号 + 1 如果真 (寻找文本 (当前行, “目标配置”, , 假) ≠ -1) 调试输出 (“找到目标配置,行号:” + 到文本 (行号)) 跳出循环 () 如果真结束 循环判断尾 (文件句柄 ≠ 0) 关闭文件 (文件句柄)这里先用循环判断首读第一行,再判断是否为空文件;如果读到目标关键词就跳出循环;如果读到文件末尾还没找到,则当前行 = 空文本触发跳出。整个逻辑层层递进,不容易漏读。
7.2 模拟重试直到成功
网络请求失败需要重试时,通常不知道第几次能成功。这时候可以用判断循环首控制重试次数上限,用跳出循环处理成功情况:
.局部变量 尝试次数, 整数型 .局部变量 请求成功, 逻辑型 请求成功 = 假 尝试次数 = 0 判断循环首 (尝试次数 < 5 且 请求成功 = 假) 尝试次数 = 尝试次数 + 1 请求成功 = 发送网络请求 () 如果真 (请求成功 = 真) 跳出循环 () 如果真结束 延时 (500) 判断循环尾 () 如果真 (请求成功 = 假) 信息框 (“重试 5 次仍然失败”, 0, , ) 如果真结束这个模式把“最多重试 5 次”的约束放在判断条件里,循环不会无限卡死。成功时跳出提前结束,失败时超过 5 次自动退出。用判断循环首而不是循环判断首,是因为一次尝试都不用做的情况下,直接判断条件更自然。
7.3 循环判断首在菜单操作中的用法
写窗口程序时,经常会有“确认对话框弹出后,等待用户点击按钮”的需求。点击按钮前窗口必须保持响应,可以用循环判断首:
循环判断首 () 处理事件 () 延时 (50) 循环判断尾 (确认窗口是否已经关闭 且 用户未点击)由于至少要显示一次窗口消息,这种场景天然适合先执行后判断。
写在最后的一点经验
这两个命令,名字看上去像双胞胎,实际上一个是“先看条件,再进门”,一个是“先进门,再看条件”。我自己记法是:“判断循环首”四个字里,“判断”在前面;“循环判断首”四个字里,“循环”在前面。谁在前就先执行谁。
写易语言流程控制时,我最常犯的错误就是条件里少更新变量。后来每次写循环,我都会先问自己三个问题:这个循环最少要执行几次?什么时候结束?循环体里会不会改变结束条件?把这三个问题想清楚,“循环判断首”和“判断循环首”就不会再坑到你了。