找回密码
立即注册
搜索
发回帖 发新帖

6117

积分

0

好友

771

主题
发表于 昨天 23:38 | 查看: 5| 回复: 0

本篇内容

  • WHILE ... DO 循环
  • REPEAT ... UNTIL 循环
  • 典型应用:输入验证
  • 核心区别对比

While...do 和 Repeat...until 是两种基于布尔条件控制的循环结构。它们弥补了 for 循环只能按固定步长迭代的不足,适用于循环次数未知的场景。

WHILE ... DO 循环

由于 for ... do 循环无法轻松满足所有迭代需求,Pascal 另外提供了两种由布尔表达式控制的循环结构。第一种便是 while ... do 循环:

while <布尔表达式> do <语句>;

只要布尔表达式的值为 True,循环体就会持续执行;若初始判断即为 False,则循环体一次也不会执行。

如果需要,你可以用 while 循环来模拟 for 循环的行为:

<变量> := <初值>;
while <变量> <= <终值> do
begin
  <语句>;
  <变量> := Succ(<变量>)  { 等价于变量自增1 }
end;

若需要自定义步长,只需修改循环体内的递增语句即可。例如,要实现步长为 3 的循环,可将最后一句改为:

<变量> := <变量> + 3;

当然,while 循环的用途远不止模仿 for 循环。下面是一个 二分查找(Binary Search) 的经典示例。该算法在有序列表中查找目标值,直到找到或确认不存在为止。二分查找的优势在于效率极高:对于包含 $n$ 个元素的列表,最多只需 $\log_2 n$ 次比较。这意味着即使列表有 1024 个元素,循环也最多执行 10 次。

procedure BinarySearch(DKey: ListVal; 
                       var Index: Integer; 
                       var Found: Boolean);
{
  本过程在有序数组 List[IMin..IMax] 中对 DKey 进行二分查找。
  前提条件:List 已按升序排列,即 List[I] <= List[I+1]
  功能:查找使得 DKey = List[Index] 的索引值
  返回:若找到则 Found = True,否则 Found = False
}
var
  Upper, Lower: Integer;
begin
  Upper := IMax;
  Lower := IMin;
  Found := False;

  while not Found and (Lower <= Upper) do
  begin
    Index := (Upper + Lower) div 2;

    if DKey < List[Index] then
      Upper := Pred(Index)       { 目标在左半区 }
    else if DKey > List[Index] then
      Lower := Succ(Index)       { 目标在右半区 }
    else
      Found := True              { 找到目标 }
  end;
end; { of proc BinarySearch }

每次进入循环体之前,先计算布尔表达式的值。如果初始条件即为 False,循环体一次也不会执行。

REPEAT ... UNTIL 循环

第三种循环结构是 repeat ... until,其语法格式如下:

repeat
  <语句1>;
  <语句2>;
  ...
  <语句n>
until <布尔条件>;

它与 while ... do 循环存在三个关键区别:

  1. 至少执行一次:循环体会先执行,然后再判断布尔条件。因此无论条件是否成立,语句至少会执行一次。
  2. 终止逻辑相反:当布尔条件为 False 时继续循环,为 True 时终止;而 while 循环恰恰相反(为 True 时继续)。
  3. 天然支持多语句:repeat ... until 本身就能包裹多条语句,无需像其他控制结构那样额外使用 begin ... end 复合语句块。

典型应用:输入验证

repeat 循环最常见的用途之一是输入校验:反复提示用户输入,直到获得合法值为止。

以下示例实现了一个“防呆”整数输入过程。它会持续要求用户输入一个位于 [Low, High] 范围内的整数,并在以下两种情况下重新提示:

  1. 发生 I/O 错误(如输入了非数字字符);
  2. 输入的数值超出允许范围。
program TestGetInteger;

type
  Prompt = string[80];

procedure GetInteger(var Val: Integer; 
                     Msg: Prompt; 
                     Low, High: Integer);
begin
  {$I-, R-}  { 关闭 I/O 检查和范围检查 }
  repeat
    Write(Msg);
    ReadLn(Val);
  until (IOresult = 0) and (Low <= Val) and (Val <= High);
  {$I+, R+}  { 恢复所有检查 }
end; { of proc GetInteger }

这段代码实现了健壮的整数输入机制。无论用户如何误操作(输入字母、超范围数值等),程序都会持续要求重新输入,直到获得格式正确且在有效范围内的值为止。

核心区别对比

特性 While...do Repeat...until
判断时机 循环前 循环后
最少执行次数 0 次 1 次
继续/终止逻辑 True → 继续 True → 终止
多语句包裹 需要 begin...end 不需要(自带块作用域)
分号 do 后面无分号 until 后面有分号
变量作用域 循环体内声明的变量外部不可见 repeat..until 内声明的变量在 until 条件中可见

更多 Lazarus/Pascal 实战内容,可以在 云栈社区 继续查阅。




上一篇:RTL封装成C++函数:软硬件协同功能验证实践
下一篇:凯文·凯利AI预测:未来十年没有AGI,99%的AI隐形运行
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-4 03:00 , Processed in 0.092740 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表