SAP-ABAP:条件判断与循环控制语句(7篇)第六篇:实战演练:用条件判断+循环实现经典算法与业务场景
2026/5/28 9:30:47 网站建设 项目流程

条件判断与循环控制语句(7篇)

第六篇:实战演练:用条件判断+循环实现经典算法与业务场景

从基础的IF分支到多级循环,条件判断和循环控制是程序逻辑的核心。但只懂语法还不够,真正的能力体现在用它们解决实际问题。本文将通过四个典型场景——冒泡排序(算法基础)、九九乘法表(嵌套循环)、用户权限校验(业务逻辑)、猜数字游戏(交互与循环控制),手把手拆解从需求分析到代码落地的完整思路。无论你是初学者还是寻求进阶的开发者,都能从中获得将语法知识转化为实战能力的启发。


一、场景一:冒泡排序——经典算法中的条件判断与嵌套循环

1.1 需求分析

冒泡排序是最基础的排序算法。其核心思想:重复遍历待排序的数列,每次比较相邻两个元素,若顺序错误则交换。每轮遍历都会将当前最大(或最小)的元素“冒泡”到末端。算法包含两层循环:外层控制遍历轮数,内层负责相邻比较和交换。

1.2 算法设计

  • 输入:内表lt_numbers,类型为STANDARD TABLE OF i
  • 输出:排序后的内表(升序)。
  • 步骤:
    1. 获取内表行数n
    2. 外层循环n-1次。
    3. 内层循环n-i-1次(i为外层循环索引),比较相邻元素,若lt_numbers[j] > lt_numbers[j+1]则交换。
    4. 可增加标志位优化:若某轮未发生交换,说明已有序,提前退出。

1.3 ABAP代码实现

FORM bubble_sort CHANGING ct_numbers TYPE STANDARD TABLE OF i. DATA: lv_len TYPE i, lv_temp TYPE i, lv_swapped TYPE abap_bool. lv_len = lines( ct_numbers ). DO lv_len - 1 TIMES. lv_swapped = abap_false. DATA(lv_outer_idx) = sy-index. DO lv_len - lv_outer_idx TIMES. DATA(lv_inner_idx) = sy-index. " 读取相邻两个元素(注意索引从1开始,需转换) READ TABLE ct_numbers INDEX lv_inner_idx INTO DATA(lv_left). READ TABLE ct_numbers INDEX lv_inner_idx + 1 INTO DATA(lv_right). IF lv_left > lv_right. " 交换 lv_temp = lv_left. MODIFY ct_numbers INDEX lv_inner_idx FROM lv_right. MODIFY ct_numbers INDEX lv_inner_idx + 1 FROM lv_temp. lv_swapped = abap_true. ENDIF. ENDDO. IF lv_swapped = abap_false. EXIT. " 已经有序,提前退出外层循环 ENDIF. ENDDO. ENDFORM.

1.4 测试代码

DATA lt_nums TYPE STANDARD TABLE OF i. lt_nums = VALUE #( ( 5 ) ( 2 ) ( 9 ) ( 1 ) ( 5 ) ( 6 ) ). PERFORM bubble_sort CHANGING lt_nums. LOOP AT lt_nums INTO DATA(lv_num). WRITE / lv_num. ENDLOOP.

1.5 要点总结

  • 嵌套循环的索引控制:外层用sy-index,内层用另一个sy-index(由于ABAP中sy-index在嵌套循环中共享同一值,因此内层循环必须将sy-index立即赋值给局部变量,否则会混乱。但上述代码中,每次进入内层DO都会刷新sy-index,这是安全的,因为内层DOsy-index是独立的。更好的实践:显式声明局部变量,避免依赖sy-index。)
  • 优化:使用MODIFY ... INDEX修改内表元素。
  • 条件判断:IF lv_left > lv_right决定是否交换。

二、场景二:九九乘法表——嵌套循环与格式化输出

2.1 需求分析

输出以下形式的乘法表:

1×1=1 1×2=2 2×2=4 1×3=3 2×3=6 3×3=9 ...

要求:每行输出与行号对应的乘法算式,算式之间用空格分隔,每行末换行。

2.2 算法设计

  • 外层循环变量i从1到9。
  • 内层循环变量j从1到i
  • 输出j × i = i*j,算式间用制表符或空格分隔。

2.3 ABAP代码实现

DATA: lv_i TYPE i, lv_j TYPE i, lv_output TYPE string. DO 9 TIMES. lv_i = sy-index. CLEAR lv_output. DO lv_i TIMES. lv_j = sy-index. CONCATENATE lv_output ` ` lv_j `×` lv_i `=` lv_i * lv_j INTO lv_output. " 或者使用字符串模板更优雅: " lv_output = |{ lv_output } { lv_j }×{ lv_i }={ lv_i * lv_j }|. ENDDO. SHIFT lv_output LEFT. " 去掉开头的空格 WRITE / lv_output. ENDDO.

2.4 运行效果

1×1=1 1×2=2 2×2=4 1×3=3 2×3=6 3×3=9 ...

2.5 要点总结

  • 嵌套循环中,外层循环控制行数,内层控制每行算式个数。
  • 字符串拼接技巧:使用CONCATENATE或字符串模板。
  • 内层循环次数依赖于外层循环变量,体现循环依赖。

三、场景三:用户权限校验——多条件判断与标志位

3.1 需求分析

某系统需校验用户是否有权执行某个操作。权限规则:

  • 用户角色为“管理员”(ROLE = 'ADMIN')→ 直接通过。
  • 用户角色为“普通用户”(ROLE = 'USER')且满足以下所有条件时通过:
    • 操作类型为允许列表中的一种(ACTION IN ('READ','PRINT'))。
    • 用户所属部门与资源部门相同(user_dep = resource_dep)。
    • 资源不是“机密级”(resource_level <> 'CONFIDENTIAL')。
  • 其他情况均拒绝。

3.2 算法设计

  • 使用卫语句优先处理管理员,简化主干逻辑。
  • 用布尔变量记录各个条件,最后组合判断。

3.3 ABAP代码实现

METHODS: check_authorization IMPORTING iv_role TYPE string iv_action TYPE string iv_user_dep TYPE string iv_resource_dep TYPE string iv_resource_level TYPE string RETURNING VALUE(rv_allowed) TYPE abap_bool. METHOD check_authorization. " 管理员直接通过 IF iv_role = 'ADMIN'. rv_allowed = abap_true. RETURN. ENDIF. " 非管理员,必须角色为普通用户 IF iv_role <> 'USER'. rv_allowed = abap_false. RETURN. ENDIF. " 普通用户权限校验 DATA(lv_action_ok) = COND #( WHEN iv_action IN ('READ', 'PRINT') THEN abap_true ELSE abap_false ). DATA(lv_department_ok) = COND #( WHEN iv_user_dep = iv_resource_dep THEN abap_true ELSE abap_false ). DATA(lv_level_ok) = COND #( WHEN iv_resource_level <> 'CONFIDENTIAL' THEN abap_true ELSE abap_false ). rv_allowed = lv_action_ok AND lv_department_ok AND lv_level_ok. ENDMETHOD.

3.4 测试用例

DATA(lv_allowed) = check_authorization( iv_role = 'USER' iv_action = 'READ' iv_user_dep = 'SALES' iv_resource_dep = 'SALES' iv_resource_level = 'PUBLIC' ). WRITE: '是否允许:', lv_allowed. " 输出 X(允许)

3.5 要点总结

  • 卫语句使代码层次清晰,异常情况提前返回。
  • 布尔变量提取使组合条件自文档化。
  • IN运算符简化多值判断。

四、场景四:猜数字游戏——循环与条件中断

4.1 需求分析

程序随机生成一个1-100之间的整数,让用户猜测。每次猜测后提示“猜大了”、“猜小了”或“恭喜猜中”。用户最多猜10次,若10次未中则公布答案并结束。同时,用户可随时输入“退出”终止游戏。

4.2 算法设计

  • 使用cl_abap_random_int生成随机数。
  • DO无限循环,内部用IF判断用户输入,用EXIT退出循环。
  • 维护猜测次数计数器,达到上限时退出并揭示答案。
  • 处理用户输入“退出”关键字。

4.3 ABAP代码实现

REPORT z_guess_number. DATA: lv_secret TYPE i, lv_guess TYPE string, lv_num TYPE i, lv_attempts TYPE i VALUE 0, lv_max_attempts TYPE i VALUE 10. " 生成1-100随机数 DATA(lo_rand) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) min = 1 max = 100 ). lv_secret = lo_rand->get_next( ). WRITE: / '猜数字游戏(1-100),你有', lv_max_attempts, '次机会。输入"退出"结束游戏。'. DO. " 猜测次数限制 lv_attempts = lv_attempts + 1. IF lv_attempts > lv_max_attempts. WRITE: / '很遗憾,10次机会已用完。答案是', lv_secret, '。游戏结束。'. EXIT. ENDIF. " 获取用户输入 WRITE: / '第', lv_attempts, '次猜测:'. READ lv_guess. IF lv_guess = '退出' OR lv_guess = 'EXIT'. WRITE / '游戏已退出。'. EXIT. ENDIF. " 尝试转换为数字 TRY. lv_num = CONV i( lv_guess ). CATCH cx_sy_conversion_no_number. WRITE / '请输入有效的数字或"退出"。'. lv_attempts = lv_attempts - 1. " 无效输入不消耗次数 CONTINUE. ENDTRY. " 判断大小 IF lv_num < lv_secret. WRITE / '猜小了,再试试。'. ELSEIF lv_num > lv_secret. WRITE / '猜大了,再试试。'. ELSE. WRITE / '恭喜!猜中了!共猜测', lv_attempts, '次。'. EXIT. ENDIF. ENDDO.

4.4 交互示例

猜数字游戏(1-100),你有10次机会。输入"退出"结束游戏。 第1次猜测: 50 猜小了,再试试。 第2次猜测: 75 猜大了,再试试。 ... 第5次猜测: 67 恭喜!猜中了!共猜测5次。

4.5 要点总结

  • 随机数生成使用标准类cl_abap_random_int
  • DO...EXIT构造后置条件循环(至少执行一次,但本程序中是在每次迭代开始时检查次数,也可用WHILE)。
  • 使用CONTINUE跳过无效输入,且不增加有效猜测计数。
  • 异常捕获处理非数字输入。
  • 多条件退出:次数耗尽、猜中、用户主动退出。

五、综合对比与经验提炼

场景核心技术循环结构条件判断亮点
冒泡排序算法逻辑嵌套DO比较+交换,提前退出优化
九九乘法表格式化输出嵌套DO,内层次数依赖外层无复杂条件,主要控制循环边界
权限校验业务规则无循环卫语句、布尔变量提取、IN运算符
猜数字交互+随机DO无限循环 +EXIT多分支退出、异常处理、CONTINUE

核心收获

  • 条件判断的嵌套深度直接影响可读性,应优先使用卫语句和布尔变量扁平化。
  • 循环的选择:明确次数用DO...TIMES;不确定次数用WHILEDO...EXIT
  • 嵌套循环中注意索引变量的独立性,避免依赖全局sy-index
  • 提前退出(EXIT)和跳过(CONTINUE)是精细化控制循环流程的利器。

通过这四个场景的实战演练,相信你已经能灵活运用条件判断和循环控制解决实际问题。下一篇我们将聚焦性能优化,分析条件与循环代码的常见性能瓶颈及优化方案,让程序不仅正确,而且高效。

📌下篇预告:性能优化:条件与循环代码的常见性能瓶颈与优化方案

作者:你的ABAP学习伙伴
版本记录:2026年5月

💬 你在实际开发中还遇到过哪些需要巧妙结合条件与循环的场景?欢迎留言分享。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询