返回首页

COBOL 过程部与语句

COBOL 过程部与语句

本章讲解 PROCEDURE DIVISION 中的核心语句:赋值、运算、条件、循环、段落调用。

目录

  1. 段落与节
  2. 赋值语句 MOVE
  3. 算术语句
  4. 条件语句 IF
  5. 分支语句 EVALUATE
  6. 循环语句 PERFORM
  7. 输入输出 DISPLAY / ACCEPT
  8. 字符串操作
  9. 内置函数
  10. 实战:snake.cob 的语句分析

1. 段落与节

PROCEDURE DIVISION 由段落(Paragraph)组成,段落可组织为节(Section)。

1
2
3
4
5
6
7
8
9
10
11
12
13
PROCEDURE DIVISION.
MAIN-PROCEDURE.
PERFORM INIT-GAME
PERFORM GAME-LOOP UNTIL WS-RUNNING = 0
STOP RUN.

INIT-GAME.
MOVE 3 TO WS-SNAKE-LEN
MOVE 4 TO WS-DIR.

GAME-LOOP.
PERFORM BUILD-GRID
PERFORM SHOW-GAME.

规则:

  • 段落名从 A 区开始,以 . 结尾
  • 段落内的语句从 B 区开始
  • 段落名是标签,通过 PERFORM 调用
  • 段落名不能与保留字冲突

2. 赋值语句 MOVE

MOVE 是最基本的赋值语句。

1
2
3
4
MOVE 100 TO WS-COUNT.
MOVE "Hello" TO WS-NAME.
MOVE WS-A TO WS-B.
MOVE SPACES TO WS-LINE.

组合项赋值

1
2
3
4
5
6
01 WS-DATE.
05 WS-YEAR PIC 9(4).
05 WS-MONTH PIC 9(2).
05 WS-DAY PIC 9(2).

MOVE "20261008" TO WS-DATE. *> 一次性填充整个组合项

多目标赋值

1
MOVE 0 TO WS-A WS-B WS-C.

类型转换规则

  • 数值 → 字符:右对齐,左侧补零
  • 字符 → 数值:需为合法数字,否则结果未定义
  • 长度不匹配:字符型左对齐截断/补空格,数值型右对齐

3. 算术语句

ADD(加)

1
2
3
ADD 1 TO WS-COUNT.
ADD 1 TO WS-SCORE WS-STEPS. *> 多目标
ADD WS-A WS-B GIVING WS-SUM. *> 结果存入新变量

SUBTRACT(减)

1
2
SUBTRACT 1 FROM WS-COUNT.
SUBTRACT WS-A FROM WS-B GIVING WS-DIFF.

MULTIPLY(乘)

1
2
MULTIPLY WS-A BY WS-B.
MULTIPLY WS-A BY WS-B GIVING WS-PROD.

DIVIDE(除)

1
2
DIVIDE WS-A BY WS-B GIVING WS-QUOT.
DIVIDE WS-A INTO WS-B GIVING WS-QUOT REMAINDER WS-REM.

COMPUTE(复合运算)

最灵活,支持表达式:

1
2
3
4
COMPUTE WS-NEW-Y = WS-SY(1) - 1.
COMPUTE WS-DIST = FUNCTION ABS(WS-TRY-X - WS-FOOD-X) +
FUNCTION ABS(WS-TRY-Y - WS-FOOD-Y).
COMPUTE WS-SEED = FUNCTION NUMVAL(WS-TIMESTAMP(9:8)).

运算符: + - * / **(幂)

ROUNDED 与 ON SIZE ERROR

1
2
3
COMPUTE WS-AVG ROUNDED = WS-TOTAL / WS-COUNT.
ADD 1 TO WS-COUNT
ON SIZE ERROR DISPLAY "溢出!".

4. 条件语句 IF

基本形式

1
2
3
IF WS-SCORE > 100
DISPLAY "优秀"
END-IF.

IF-ELSE

1
2
3
4
5
6
IF WS-NEW-X < 1 OR WS-NEW-X > 20
MOVE "撞到墙壁" TO WS-END-REASON
MOVE 0 TO WS-RUNNING
ELSE
PERFORM MOVE-FORWARD
END-IF.

比较运算符

运算符 等价写法 含义
= EQUAL 等于
< LESS 小于
> GREATER 大于
<= NOT > 小于等于
>= NOT < 大于等于
<> NOT = 不等于

逻辑运算符

1
2
3
4
5
6
7
IF WS-A > 0 AND WS-B > 0
DISPLAY "都为正"
END-IF.

IF WS-X = 1 OR WS-X = 2 OR WS-X = 3
DISPLAY "在范围内"
END-IF.

复合条件与括号

1
2
3
4
IF WS-DIST < WS-BEST-DIST OR
(WS-DIST = WS-BEST-DIST AND WS-TRY-DIR = WS-DIR)
MOVE WS-DIST TO WS-BEST-DIST
END-IF.

条件名(88 层级)

1
2
3
4
5
6
01 WS-RUNNING PIC 9 VALUE 1.
88 GAME-OVER VALUE 0.

IF GAME-OVER
DISPLAY "游戏结束"
END-IF.

5. 分支语句 EVALUATE

EVALUATE 类似其他语言的 switch,但更强大。

基本形式

1
2
3
4
5
6
7
8
9
10
11
12
EVALUATE WS-DIR
WHEN 1
COMPUTE WS-NEW-Y = WS-SY(1) - 1
WHEN 2
COMPUTE WS-NEW-Y = WS-SY(1) + 1
WHEN 3
COMPUTE WS-NEW-X = WS-SX(1) - 1
WHEN 4
COMPUTE WS-NEW-X = WS-SX(1) + 1
WHEN OTHER
DISPLAY "无效方向"
END-EVALUATE.

多值匹配

1
2
3
4
5
6
7
8
EVALUATE WS-CODE
WHEN 1 WHEN 2 WHEN 3
DISPLAY "低"
WHEN 4 THRU 6
DISPLAY "中"
WHEN OTHER
DISPLAY "高"
END-EVALUATE.

条件匹配(EVALUATE TRUE)

1
2
3
4
5
6
7
8
EVALUATE TRUE
WHEN WS-SCORE >= 90
DISPLAY "A"
WHEN WS-SCORE >= 60
DISPLAY "B"
WHEN OTHER
DISPLAY "C"
END-EVALUATE.

6. 循环语句 PERFORM

PERFORM 是 COBOL 唯一的循环/调用机制,功能丰富。

6.1 调用段落(无循环)

1
2
PERFORM INIT-GAME.
PERFORM SHOW-GAME.

6.2 条件循环(先判断)

1
PERFORM GAME-LOOP UNTIL WS-RUNNING = 0.

6.3 条件循环(后判断,至少执行一次)

1
2
PERFORM PROCESS-RECORD WITH TEST AFTER
UNTIL WS-EOF = 1.

6.4 计数循环(VARYING)

1
2
3
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 12
DISPLAY WS-I
END-PERFORM.

6.5 嵌套循环

1
2
3
4
5
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 12
PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 20
MOVE 0 TO WS-CELL(WS-I, WS-J)
END-PERFORM
END-PERFORM.

6.6 内联 PERFORM(END-PERFORM)

1
2
3
4
5
6
PERFORM UNTIL WS-I >= WS-SNAKE-LEN
COMPUTE WS-K = WS-SNAKE-LEN - WS-I + 1
COMPUTE WS-J = WS-K - 1
MOVE WS-SX(WS-J) TO WS-SX(WS-K)
ADD 1 TO WS-I
END-PERFORM.

6.7 提前退出

1
2
3
4
5
PERFORM VARYING WS-K FROM 1 BY 1 UNTIL WS-K > WS-SNAKE-LEN
IF WS-SX(WS-K) = WS-NEW-X
EXIT PERFORM *> 跳出当前循环
END-IF
END-PERFORM.
  • EXIT PERFORM:跳出循环
  • EXIT PARAGRAPH:跳出当前段落
  • EXIT SECTION:跳出当前节

7. 输入输出 DISPLAY / ACCEPT

DISPLAY(输出)

1
2
3
DISPLAY "Hello, World!".
DISPLAY WS-SCORE.
DISPLAY "得分: " WS-SCORE-OUT " 长度: " WS-LEN-OUT.

不换行输出

1
DISPLAY WS-CLEAR-SEQ WITH NO ADVANCING.

WITH NO ADVANCING 抑制自动换行,常用于输出 ANSI 转义序列。

ACCEPT(输入)

1
2
3
4
ACCEPT WS-NAME.
ACCEPT WS-NAME FROM CONSOLE.
ACCEPT WS-DATE FROM DATE. *> 获取系统日期 YYMMDD
ACCEPT WS-TIME FROM TIME. *> 获取系统时间 HHMMSS

8. 字符串操作

8.1 引用修改(Reference Modification)

用 (起始位置:长度) 截取子串:

1
2
3
 01 WS-TIMESTAMP PIC X(21).
COMPUTE WS-SEED = FUNCTION NUMVAL(WS-TIMESTAMP(9:8)).
*> 取第 9 位开始的 8 个字符

8.2 STRING(拼接)

1
2
3
4
5
STRING WS-FIRST DELIMITED BY SPACE
" " DELIMITED BY SIZE
WS-LAST DELIMITED BY SPACE
INTO WS-FULL-NAME
END-STRING.

8.3 UNSTRING(拆分)

1
2
3
UNSTRING WS-LINE DELIMITED BY ","
INTO WS-FIELD-1 WS-FIELD-2 WS-FIELD-3
END-UNSTRING.

8.4 INSPECT(检查/替换)

1
2
INSPECT WS-TEXT TALLYING WS-COUNT FOR ALL "a".
INSPECT WS-TEXT REPLACING ALL "a" BY "A".

9. 内置函数

COBOL 提供丰富的内置函数(Intrinsic Functions),用 FUNCTION 函数名(参数) 调用。

函数 说明 示例
ABS 绝对值 FUNCTION ABS(-5) → 5
MOD 取模 FUNCTION MOD(7, 3) → 1
INTEGER 取整 FUNCTION INTEGER(3.7) → 3
NUMVAL 字符串转数值 FUNCTION NUMVAL("123") → 123
RANDOM 随机数 [0,1) FUNCTION RANDOM
LENGTH 长度 FUNCTION LENGTH(WS-NAME)
UPPER-CASE 转大写 FUNCTION UPPER-CASE(WS-S)
LOWER-CASE 转小写 FUNCTION LOWER-CASE(WS-S)
MAX / MIN 最大/最小 FUNCTION MAX(A, B)
CURRENT-DATE 当前日期时间 FUNCTION CURRENT-DATE

示例(来自 snake.cob):

1
2
3
4
COMPUTE WS-FOOD-X =
FUNCTION INTEGER(FUNCTION RANDOM * 20) + 1.
COMPUTE WS-FOOD-Y =
FUNCTION INTEGER(FUNCTION RANDOM * 12) + 1.

10. 实战:snake.cob 的语句分析

主循环结构

1
2
3
4
5
6
7
8
9
10
11
MAIN-PROCEDURE.
PERFORM INIT-GAME
PERFORM GAME-LOOP UNTIL WS-RUNNING = 0
PERFORM SHOW-GAME
DISPLAY " "
DISPLAY "=========================================="
MOVE WS-SCORE TO WS-SCORE-OUT
DISPLAY " 游戏结束! 最终得分: " WS-SCORE-OUT
DISPLAY " 原因: " WS-END-REASON
DISPLAY "=========================================="
STOP RUN.

分析: 先初始化,然后循环执行游戏主逻辑直到 WS-RUNNING = 0,最后显示结束信息。

方向选择逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CHOOSE-DIR.
MOVE 99 TO WS-BEST-DIST
MOVE 0 TO WS-BEST-DIR
PERFORM VARYING WS-TRY-DIR FROM 1 BY 1
UNTIL WS-TRY-DIR > 4
PERFORM TEST-DIRECTION
IF WS-SAFE = 1
COMPUTE WS-DIST =
FUNCTION ABS(WS-TRY-X - WS-FOOD-X) +
FUNCTION ABS(WS-TRY-Y - WS-FOOD-Y)
IF WS-DIST < WS-BEST-DIST OR
(WS-DIST = WS-BEST-DIST AND WS-TRY-DIR = WS-DIR)
MOVE WS-DIST TO WS-BEST-DIST
MOVE WS-TRY-DIR TO WS-BEST-DIR
END-IF
END-IF
END-PERFORM
IF WS-BEST-DIR NOT = 0
MOVE WS-BEST-DIR TO WS-DIR
END-IF.

分析: 遍历 4 个方向,对每个安全方向计算到食物的曼哈顿距离,选择距离最小的方向(贪心算法)。

延时控制

1
2
3
4
5
6
7
8
DELAY.
IF WS-SCORE < 35
COMPUTE WS-DELAY-US = 200000 - WS-SCORE * 4000
ELSE
MOVE 60000 TO WS-DELAY-US
END-IF
CALL "usleep" USING BY VALUE WS-DELAY-US
END-CALL.

分析: 分数越高延时越短(速度越快),最低 60ms。通过 CALL 调用 C 库函数 usleep。


上一章: 数据类型与变量
下一章: 表与数组