- COBOL 教程
- COBOL - 首页
- COBOL - 概述
- COBOL - 环境设置
- COBOL - 程序结构
- COBOL - 基本语法
- COBOL - 数据类型
- COBOL - 基本动词
- COBOL - 数据布局
- COBOL - 条件语句
- COBOL - 循环语句
- COBOL - 字符串处理
- COBOL - 表格处理
- COBOL - 文件处理
- COBOL - 文件组织
- COBOL - 文件访问模式
- COBOL - 文件处理动词
- COBOL - 子程序
- COBOL - 内部排序
- COBOL - 数据库接口
- COBOL 有用资源
- COBOL - 问答
- COBOL - 快速指南
- COBOL - 有用资源
COBOL - 快速指南
COBOL - 概述
COBOL 简介
COBOL 是一种高级语言。必须了解 COBOL 的工作方式。计算机只理解机器代码,即 0 和 1 的二进制流。COBOL 代码必须使用编译器转换为机器代码。将程序源代码通过编译器运行。编译器首先检查是否存在任何语法错误,然后将其转换为机器语言。编译器创建一个输出文件,称为加载模块。此输出文件包含以 0 和 1 形式表示的可执行代码。
COBOL 的演变
在 20 世纪 50 年代,当世界西部的企业发展壮大时,需要自动化各种流程以简化操作,这催生了一种面向业务数据处理的高级编程语言。
1959 年,COBOL 由 CODASYL(数据系统语言会议)开发。
下一个版本 COBOL-61 于 1961 年发布,并进行了一些修订。
1968 年,COBOL 被 ANSI 批准为商业用途的标准语言(COBOL-68)。
它分别于 1974 年和 1985 年进行了修订,以开发名为 COBOL-74 和 COBOL-85 的后续版本。
2002 年,发布了面向对象的 COBOL,它可以将封装对象作为 COBOL 编程的常规部分使用。
COBOL 的重要性
COBOL 是第一种广泛使用的高级编程语言。它是一种类似英语的语言,用户友好。所有指令都可以用简单的英语单词进行编码。
COBOL 也用作自文档语言。
COBOL 可以处理海量数据处理。
COBOL 与其以前的版本兼容。
COBOL 具有有效的错误消息,因此,错误的解决更加容易。
COBOL 的特点
标准语言
COBOL 是一种标准语言,可以在 IBM AS/400、个人电脑等机器上编译和执行。
面向业务
COBOL 旨在用于与金融领域、国防领域等相关的面向业务的应用程序。由于其高级文件处理功能,它可以处理海量数据。
健壮的语言
COBOL 是一种健壮的语言,因为它几乎在所有计算机平台上都提供了大量的调试和测试工具。
结构化语言
COBOL 中提供了逻辑控制结构,这使得它更容易阅读和修改。COBOL 具有不同的部分,因此易于调试。
COBOL - 环境设置
我们已在线设置了 COBOL 编程环境,以便您可以在线编译和执行所有可用的示例。它让您对正在阅读的内容充满信心,并使您能够使用不同的选项验证程序。随时修改任何示例并在网上执行。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. PROCEDURE DIVISION. DISPLAY 'Hello World'. STOP RUN.
对于本教程中给出的大多数示例,您都可以在我们网站代码部分的右上角找到“试一试”选项,该选项将带您进入在线编译器。因此,只需使用它并享受您的学习。
在 Windows/Linux 上安装 COBOL
有许多可用于 Windows 的免费大型机仿真器,可用于编写和学习简单的 COBOL 程序。
其中一个仿真器是 Hercules,它可以通过以下几个简单的步骤轻松安装在 Windows 上:
下载并安装 Hercules 仿真器,该仿真器可从 Hercules 主页获得:www.hercules-390.eu
在 Windows 机器上安装软件包后,它将创建一个类似于C:/hercules/mvs/cobol的文件夹。
运行命令提示符 (CMD) 并转到 CMD 上的 C:/hercules/mvs/cobol 目录。
有关编写和执行 JCL 和 COBOL 程序的各种命令的完整指南可在以下网址找到:
www.jaymoseley.com/hercules/installmvs/instmvs2.htm
Hercules 是大型机 System/370 和 ESA/390 架构以及最新的 64 位 z/Architecture 的开源软件实现。Hercules 在 Linux、Windows、Solaris、FreeBSD 和 Mac OS X 上运行。
用户可以通过多种方式连接到大型机服务器,例如瘦客户端、虚拟终端、虚拟客户端系统 (VCS) 或虚拟桌面系统 (VDS)。每个有效用户都会获得一个登录 ID 以进入 Z/OS 接口(TSO/E 或 ISPF)。
编译 COBOL 程序
为了使用 JCL 以批处理模式执行 COBOL 程序,需要编译程序,并创建一个包含所有子程序的加载模块。JCL 在执行时使用加载模块,而不是实际程序。加载库被连接起来,并在执行时使用JCLLIB或STEPLIB传递给 JCL。
有许多大型机编译器实用程序可用于编译 COBOL 程序。一些公司使用 Change Management 工具(如Endevor),它可以编译并存储程序的每个版本。这有助于跟踪对程序所做的更改。
//COMPILE JOB ,CLASS=6,MSGCLASS=X,NOTIFY=&SYSUID //* //STEP1 EXEC IGYCRCTL,PARM=RMODE,DYNAM,SSRANGE //SYSIN DD DSN=MYDATA.URMI.SOURCES(MYCOBB),DISP=SHR //SYSLIB DD DSN=MYDATA.URMI.COPYBOOK(MYCOPY),DISP=SHR //SYSLMOD DD DSN=MYDATA.URMI.LOAD(MYCOBB),DISP=SHR //SYSPRINT DD SYSOUT=* //*
IGYCRCTL 是一个 IBM COBOL 编译器实用程序。编译器选项通过 PARM 参数传递。在上面的示例中,RMODE 指示编译器在程序中使用相对寻址模式。COBOL 程序通过 SYSIN 参数传递。Copybook 是 SYSLIB 中程序使用的库。
执行 COBOL 程序
下面是一个 JCL 示例,其中程序 MYPROG 使用输入文件 MYDATA.URMI.INPUT 执行,并生成两个写入卷轴的输出文件。
//COBBSTEP JOB CLASS=6,NOTIFY=&SYSUID // //STEP10 EXEC PGM=MYPROG,PARM=ACCT5000 //STEPLIB DD DSN=MYDATA.URMI.LOADLIB,DISP=SHR //INPUT1 DD DSN=MYDATA.URMI.INPUT,DISP=SHR //OUT1 DD SYSOUT=* //OUT2 DD SYSOUT=* //SYSIN DD * //CUST1 1000 //CUST2 1001 /*
MYPROG 的加载模块位于 MYDATA.URMI.LOADLIB 中。需要注意的是,上述 JCL 只能用于非 DB2 COBOL 模块。
执行 COBOL-DB2 程序
为了运行 COBOL-DB2 程序,JCL 和程序中使用了专门的 IBM 实用程序;DB2 区域和所需参数作为输入传递给实用程序。
运行 COBOL-DB2 程序的步骤如下:
当编译 COBOL-DB2 程序时,除了加载模块外,还会创建一个 DBRM(数据库请求模块)。DBRM 包含 COBOL 程序的 SQL 语句,并对其语法进行了检查以确保正确。
DBRM 绑定到 COBOL 将在其上运行的 DB2 区域(环境)。这可以通过 JCL 中的 IKJEFT01 实用程序完成。
绑定步骤完成后,使用 IKJEFT01(再次)运行 COBOL-DB2 程序,并将加载库和 DBRM 库作为输入传递给 JCL。
//STEP001 EXEC PGM=IKJEFT01 //* //STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR //* //input files //output files //SYSPRINT DD SYSOUT=* //SYSABOUT DD SYSOUT=* //SYSDBOUT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //DISPLAY DD SYSOUT=* //SYSOUT DD SYSOUT=* //SYSTSPRT DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(MYCOBB) PLAN(PLANNAME) PARM(parameters to cobol program) - LIB('MYDATA.URMI.LOADLIB') END /*
在上面的示例中,MYCOBB 是使用 IKJEFT01 运行的 COBOL-DB2 程序。请注意,程序名称、DB2 子系统 ID(SSID)和 DB2 计划名称在 SYSTSIN DD 语句中传递。DBRM 库在 STEPLIB 中指定。
COBOL - 程序结构
COBOL 程序结构由以下图像所示的部分组成:
下面简要介绍了这些部分:
节是程序逻辑的逻辑细分。节是段落的集合。
段落是节或部分的细分。它是一个后跟句点的用户定义或预定义名称,包含零个或多个句子/条目。
句子是一个或多个语句的组合。句子仅出现在过程部分。句子必须以句点结尾。
语句是执行某些处理的有意义的 COBOL 语句。
字符在层次结构中最低,并且不可分割。
您可以将上述术语与以下示例中的 COBOL 程序关联:
PROCEDURE DIVISION. A0000-FIRST-PARA SECTION. FIRST-PARAGRAPH. ACCEPT WS-ID - Statement-1 -----| MOVE '10' TO WS-ID - Statement-2 |-- Sentence - 1 DISPLAY WS-ID - Statement-3 -----| .
部分
COBOL 程序由四个部分组成。
标识部分
它是每个 COBOL 程序的第一个也是唯一一个必须有的部分。程序员和编译器使用此部分来识别程序。在此部分中,PROGRAM-ID 是唯一必须有的段落。PROGRAM-ID 指定程序名称,程序名称可以包含 1 到 30 个字符。
使用在线的实时演示选项试用以下示例。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. PROCEDURE DIVISION. DISPLAY 'Welcome to Tutorialspoint'. STOP RUN.
以下是执行上述 COBOL 程序的JCL。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Welcome to Tutorialspoint
环境部分
环境部分用于向程序指定输入和输出文件。它包含两个节:
配置节提供有关编写和执行程序的系统的信息。它包含两个段落:
源计算机 - 用于编译程序的系统。
目标计算机 - 用于执行程序的系统。
输入输出节提供有关程序中要使用的文件的信息。它包含两个段落:
文件控制 - 提供程序中使用的外部数据集的信息。
I-O 控制 - 提供程序中使用的文件的信息。
ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. XXX-ZOS. OBJECT-COMPUTER. XXX-ZOS. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT FILEN ASSIGN TO DDNAME ORGANIZATION IS SEQUENTIAL.
数据部分
数据部分用于定义程序中使用的变量。它包含四个节:
文件节用于定义文件的记录结构。
工作存储节用于声明程序中使用的临时变量和文件结构。
本地存储节类似于工作存储节。唯一的区别是,每次程序开始执行时都会分配和初始化变量。
连接节用于描述从外部程序接收的数据名称。
COBOL 程序
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT FILEN ASSIGN TO INPUT. ORGANIZATION IS SEQUENTIAL. ACCESS IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD FILEN 01 NAME PIC A(25). WORKING-STORAGE SECTION. 01 WS-STUDENT PIC A(30). 01 WS-ID PIC 9(5). LOCAL-STORAGE SECTION. 01 LS-CLASS PIC 9(3). LINKAGE SECTION. 01 LS-ID PIC 9(5). PROCEDURE DIVISION. DISPLAY 'Executing COBOL program using JCL'. STOP RUN.
执行上述 COBOL 程序的JCL如下:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //INPUT DD DSN = ABC.EFG.XYZ,DISP = SHR
当您编译并执行上述程序时,它会生成以下结果:
Executing COBOL program using JCL
过程部分
过程部分用于包含程序的逻辑。它使用数据部分中定义的变量包含可执行语句。在此部分中,段落和节名称是用户定义的。
过程部分中必须至少有一个语句。此部分中结束执行的最后一个语句要么是STOP RUN(用于调用程序),要么是EXIT PROGRAM(用于被调用程序)。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NAME PIC A(30). 01 WS-ID PIC 9(5) VALUE '12345'. PROCEDURE DIVISION. A000-FIRST-PARA. DISPLAY 'Hello World'. MOVE 'TutorialsPoint' TO WS-NAME. DISPLAY "My name is : "WS-NAME. DISPLAY "My ID is : "WS-ID. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Hello World My name is : TutorialsPoint My ID is : 12345
COBOL - 基本语法
字符集
“字符”在层次结构中最低,它们不能再细分。COBOL 字符集包括 78 个字符,如下所示:
序号 | 字符和描述 |
---|---|
1 | A-Z 字母(大写) |
2 | a-z 字母(小写) |
3 | 0-9 数字 |
4 |
空格 |
5 | + 加号 |
6 | - 减号或连字符 |
7 | * 星号 |
8 | / 正斜杠 |
9 | $ 货币符号 |
10 | , 逗号 |
11 | ; 分号 |
12 |
. 小数点或句点 |
13 |
" 引号 |
14 |
( 左括号 |
15 |
) 右括号 |
16 |
> 大于 |
17 |
< 小于 |
18 |
: 冒号 |
19 |
' 撇号 |
20 |
= 等号 |
编码表
COBOL 的源程序必须以编译器可以接受的格式编写。COBOL 程序写在 COBOL 编码表上。编码表每一行的字符位置有 80 个。
字符位置被分成以下五个字段:
位置 | 字段 | 描述 |
---|---|---|
1-6 | 列号 | 保留用于行号。 |
7 | 指示器 | 它可以使用星号 (*) 表示注释,连字符 (-) 表示续行,以及斜杠 (/) 表示换页。 |
8-11 | 区域 A | 所有 COBOL 部、节、段落和一些特殊条目都必须从区域 A 开始。 |
12-72 | 区域 B | 所有 COBOL 语句都必须从区域 B 开始。 |
73-80 | 标识区 | 程序员可以根据需要使用它。 |
示例
以下示例显示了一个 COBOL 代码表 -
000100 IDENTIFICATION DIVISION. 000100 000200 PROGRAM-ID. HELLO. 000101 000250* THIS IS A COMMENT LINE 000102 000300 PROCEDURE DIVISION. 000103 000350 A000-FIRST-PARA. 000104 000400 DISPLAY “Coding Sheet”. 000105 000500 STOP RUN. 000106
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Coding Sheet
字符字符串
字符字符串是由单个字符组合而成的。字符字符串可以是
- 注释,
- 文字,或
- COBOL 字。
所有字符字符串都必须以**分隔符**结尾。分隔符用于分隔字符字符串。
常用分隔符 - 空格、逗号、句点、撇号、左/右括号和引号。
注释
注释是不会影响程序执行的字符字符串。它可以是任何字符组合。
注释有两种类型 -
注释行
注释行可以写在任何列中。编译器不会检查注释行的语法,并将其视为文档。
注释条目
注释条目是指包含在 Identification Division 可选段落中的条目。它们写在区域 B 中,程序员使用它进行参考。
以下示例中以**粗体**突出显示的文本是注释条目 -
000100 IDENTIFICATION DIVISION. 000100 000150 PROGRAM-ID. HELLO. 000101 000200 AUTHOR. TUTORIALSPOINT. 000102 000250* THIS IS A COMMENT LINE 000103 000300 PROCEDURE DIVISION. 000104 000350 A000-FIRST-PARA. 000105 000360/ First Para Begins - Documentation Purpose 000106 000400 DISPLAY “Comment line”. 000107 000500 STOP RUN. 000108
执行上述 COBOL 程序的**JCL** -
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Comment Line
文字
文字是在程序中直接硬编码的常量。在下面的示例中,“Hello World”是一个文字。
PROCEDURE DIVISION. DISPLAY 'Hello World'.
文字有两种类型,如下所述 -
字母数字文字
字母数字文字用引号或撇号括起来。长度最多可达 160 个字符。撇号或引号只能作为文字的一部分,前提是它们成对出现。文字的开始和结束必须相同,要么是撇号,要么是引号。
示例
以下示例显示了有效的和无效的字母数字文字 -
Valid: ‘This is valid’ "This is valid" ‘This isn’’t invalid’ Invalid: ‘This is invalid” ‘This isn’t valid’
数字文字
数字文字是 0 到 9 的数字、+、- 或小数点的组合。长度最多可达 18 个字符。符号不能是最后一个字符。小数点不能出现在末尾。
示例
以下示例显示了有效的和无效的数字文字 -
Valid: 100 +10.9 -1.9 Invalid: 1,00 10. 10.9-
COBOL 字
COBOL 字是可以用作保留字或用户定义字的字符字符串。长度最多可达 30 个字符。
用户定义
用户定义的字用于命名文件、数据、记录、段落名和节。在形成用户定义的字时,允许使用字母、数字和连字符。不能使用 COBOL 保留字。
保留字
保留字是 COBOL 中预定义的字。我们经常使用的不同类型的保留字如下 -
**关键字**,如 ADD、ACCEPT、MOVE 等。
**特殊字符**字,如 +、-、*、<、<= 等
**文字常量**是诸如 ZERO、SPACES 等的常量值。文字常量的所有常量值都在下表中列出。
文字常量
序号 | 文字常量和描述 |
---|---|
1 |
HIGH-VALUES 一个或多个字符,这些字符在降序中将位于最高位置。 |
2 |
LOW-VALUES 一个或多个字符在二进制表示中具有零。 |
3 |
ZERO/ZEROES 根据变量的大小,一个或多个零。 |
4 |
SPACES 一个或多个空格。 |
5 |
QUOTES 单引号或双引号。 |
6 |
ALL 文字 用文字填充数据项。 |
COBOL - 数据类型
Data Division 用于定义程序中使用的变量。要描述 COBOL 中的数据,必须理解以下术语 -
- 数据名
- 级别号
- Picture 子句
- Value 子句
01 TOTAL-STUDENTS PIC9(5) VALUE '125'. | | | | | | | | | | | | Level Number Data Name Picture Clause Value Clause
数据名
在 Procedure Division 中使用数据名前,必须在 Data Division 中定义它们。它们必须具有用户定义的名称;不能使用保留字。数据名称引用存储实际数据的内存位置。它们可以是基本类型或组类型。
示例
以下示例显示了有效和无效的数据名称 -
Valid: WS-NAME TOTAL-STUDENTS A100 100B Invalid: MOVE (Reserved Words) COMPUTE (Reserved Words) 100 (No Alphabet) 100+B (+ is not allowed)
级别号
级别号用于指定记录中数据的级别。它们用于区分基本项和组项。基本项可以组合在一起以创建组项。
序号 | 级别号和描述 |
---|---|
1 |
01 记录描述条目 |
2 |
02 到 49 组和基本项 |
3 |
66 重命名子句项 |
4 |
77 无法细分的项 |
5 |
88 条件名称条目 |
**基本项**不能进一步细分。级别号、数据名、Picture 子句和 Value 子句(可选)用于描述基本项。
**组项**由一个或多个基本项组成。级别号、数据名和 Value 子句(可选)用于描述组项。组级别号始终为 01。
示例
以下示例显示了组和基本项 -
DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NAME PIC X(25). ---> ELEMENTARY ITEM 01 WS-CLASS PIC 9(2) VALUE '10'. ---> ELEMENTARY ITEM 01 WS-ADDRESS. ---> GROUP ITEM 05 WS-HOUSE-NUMBER PIC 9(3). ---> ELEMENTARY ITEM 05 WS-STREET PIC X(15). ---> ELEMENTARY ITEM 05 WS-CITY PIC X(15). ---> ELEMENTARY ITEM 05 WS-COUNTRY PIC X(15) VALUE 'INDIA'. ---> ELEMENTARY ITEM
Picture 子句
Picture 子句用于定义以下项 -
**数据类型**可以是数字、字母或字母数字。数字类型仅包含 0 到 9 的数字。字母类型包含 A 到 Z 的字母和空格。字母数字类型包含数字、字母和特殊字符。
**符号**可以与数字数据一起使用。它可以是 + 或 -。
**小数点位置**可以与数字数据一起使用。假定位置是小数点的位置,不包含在数据中。
**长度**定义数据项使用的字节数。
Picture 子句中使用的符号 -
序号 | 符号和描述 |
---|---|
1 |
9 数字 |
2 |
A 字母 |
3 |
X 字母数字 |
4 |
V 隐式小数 |
5 |
S 符号 |
6 |
P 假定小数 |
示例
以下示例显示了 PIC 子句的使用 -
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC S9(3)V9(2). 01 WS-NUM2 PIC PPP999. 01 WS-NUM3 PIC S9(3)V9(2) VALUE -123.45. 01 WS-NAME PIC A(6) VALUE 'ABCDEF'. 01 WS-ID PIC X(5) VALUE 'A121$'. PROCEDURE DIVISION. DISPLAY "WS-NUM1 : "WS-NUM1. DISPLAY "WS-NUM2 : "WS-NUM2. DISPLAY "WS-NUM3 : "WS-NUM3. DISPLAY "WS-NAME : "WS-NAME. DISPLAY "WS-ID : "WS-ID. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : +000.00 WS-NUM2 : .000000 WS-NUM3 : -123.45 WS-NAME : ABCDEF WS-ID : A121$
Value 子句
Value 子句是一个可选子句,用于初始化数据项。值可以是数字文字、字母数字文字或文字常量。它可以与组项和基本项一起使用。
示例
以下示例显示了 VALUE 子句的使用 -
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 99V9 VALUE IS 3.5. 01 WS-NAME PIC A(6) VALUE 'ABCD'. 01 WS-ID PIC 99 VALUE ZERO. PROCEDURE DIVISION. DISPLAY "WS-NUM1 : "WS-NUM1. DISPLAY "WS-NAME : "WS-NAME. DISPLAY "WS-ID : "WS-ID. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 03.5 WS-NAME : ABCD WS-ID : 00
COBOL - 基本动词
COBOL 动词在过程部分用于数据处理。语句始终以 COBOL 动词开头。有几种 COBOL 动词具有不同类型的操作。
输入/输出动词
输入/输出动词用于从用户获取数据并显示 COBOL 程序的输出。以下两个动词用于此过程 -
Accept 动词
Accept 动词用于从操作系统或直接从用户获取数据,例如日期、时间和日期。如果程序正在从用户处接受数据,则需要通过 JCL 传递。在从操作系统获取数据时,将包含 FROM 选项,如下例所示 -
ACCEPT WS-STUDENT-NAME. ACCEPT WS-DATE FROM SYSTEM-DATE.
Display 动词
Display 动词用于显示 COBOL 程序的输出。
DISPLAY WS-STUDENT-NAME. DISPLAY "System date is : " WS-DATE.
COBOL 程序
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STUDENT-NAME PIC X(25). 01 WS-DATE PIC X(10). PROCEDURE DIVISION. ACCEPT WS-STUDENT-NAME. ACCEPT WS-DATE FROM DATE. DISPLAY "Name : " WS-STUDENT-NAME. DISPLAY "Date : " WS-DATE. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //INPUT DD DSN=PROGRAM.DIRECTORY,DISP=SHR //SYSIN DD * TutorialsPoint /*
当您编译并执行上述程序时,它会生成以下结果:
Name : TutorialsPoint Date : 2014-08-30
Initialize 动词
Initialize 动词用于初始化组项或基本项。具有 RENAME 子句的数据名称不能初始化。数字数据项将替换为 ZEROES。字母数字或字母数据项将替换为 SPACES。如果我们包含 REPLACING 术语,则数据项可以初始化为给定的替换值,如下例所示 -
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NAME PIC A(30) VALUE 'ABCDEF'. 01 WS-ID PIC 9(5). 01 WS-ADDRESS. 05 WS-HOUSE-NUMBER PIC 9(3). 05 WS-COUNTRY PIC X(15). 05 WS-PINCODE PIC 9(6) VALUE 123456. PROCEDURE DIVISION. A000-FIRST-PARA. INITIALIZE WS-NAME, WS-ADDRESS. INITIALIZE WS-ID REPLACING NUMERIC DATA BY 12345. DISPLAY "My name is : "WS-NAME. DISPLAY "My ID is : "WS-ID. DISPLAY "Address : "WS-ADDRESS. DISPLAY "House Number : "WS-HOUSE-NUMBER. DISPLAY "Country : "WS-COUNTRY. DISPLAY "Pincode : "WS-PINCODE. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
My name is : My ID is : 12345 Address : 000 000000 House Number : 000 Country : Pincode : 000000
Move 动词
Move 动词用于将数据从源数据复制到目标数据。它可以用于基本数据项和组数据项。对于组数据项,使用 MOVE CORRESPONDING/CORR。在试用选项中,MOVE CORR 不起作用;但在大型机服务器上,它将起作用。
要从字符串移动数据,使用 MOVE(x:l),其中 x 是起始位置,l 是长度。如果目标数据项的 PIC 子句小于源数据项的 PIC 子句,则数据将被截断。如果目标数据项的 PIC 子句大于源数据项的 PIC 子句,则将在额外的字节中添加 ZEROS 或 SPACES。以下示例使这一点变得清晰。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9). 01 WS-NUM2 PIC 9(9). 01 WS-NUM3 PIC 9(5). 01 WS-NUM4 PIC 9(6). 01 WS-ADDRESS. 05 WS-HOUSE-NUMBER PIC 9(3). 05 WS-COUNTRY PIC X(5). 05 WS-PINCODE PIC 9(6). 01 WS-ADDRESS1. 05 WS-HOUSE-NUMBER1 PIC 9(3). 05 WS-COUNTRY1 PIC X(5). 05 WS-PINCODE1 PIC 9(6). PROCEDURE DIVISION. A000-FIRST-PARA. MOVE 123456789 TO WS-NUM1. MOVE WS-NUM1 TO WS-NUM2 WS-NUM3. MOVE WS-NUM1(3:6) TO WS-NUM4. MOVE 123 TO WS-HOUSE-NUMBER. MOVE 'INDIA' TO WS-COUNTRY. MOVE 112233 TO WS-PINCODE. MOVE WS-ADDRESS TO WS-ADDRESS1. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUM3 : " WS-NUM3 DISPLAY "WS-NUM4 : " WS-NUM4 DISPLAY "WS-ADDRESS : " WS-ADDRESS DISPLAY "WS-ADDRESS1 : " WS-ADDRESS1 STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 123456789 WS-NUM2 : 123456789 WS-NUM3 : 56789 WS-NUM4 : 345678 WS-ADDRESS : 123INDIA112233 WS-ADDRESS1 : 123INDIA112233
合法移动
下表提供有关合法移动的信息 -
字母 | 字母数字 | 数字 | |
---|---|---|---|
字母 | 可能的 | 可能的 | 不可能的 |
字母数字 | 可能的 | 可能的 | 可能的 |
数字 | 不可能的 | 可能的 | 可能的 |
Add 动词
Add 动词用于将两个或多个数字相加并将结果存储在目标操作数中。
语法
以下是将两个或多个数字相加的语法 -
ADD A B TO C D ADD A B C TO D GIVING E ADD CORR WS-GROUP1 TO WS-GROUP2
在语法-1 中,将 A、B、C 相加并将结果存储在 C 中 (C=A+B+C)。将 A、B、D 相加并将结果存储在 D 中 (D = A + B + D)。
在语法-2 中,将 A、B、C、D 相加并将结果存储在 E 中 (E=A+B+C+D)。
在语法-3 中,将 WS-GROUP1 和 WS-GROUP2 中的子组项相加并将结果存储在 WS-GROUP2 中。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9) VALUE 10 . 01 WS-NUM2 PIC 9(9) VALUE 10. 01 WS-NUM3 PIC 9(9) VALUE 10. 01 WS-NUM4 PIC 9(9) VALUE 10. 01 WS-NUMA PIC 9(9) VALUE 10. 01 WS-NUMB PIC 9(9) VALUE 10. 01 WS-NUMC PIC 9(9) VALUE 10. 01 WS-NUMD PIC 9(9) VALUE 10. 01 WS-NUME PIC 9(9) VALUE 10. PROCEDURE DIVISION. ADD WS-NUM1 WS-NUM2 TO WS-NUM3 WS-NUM4. ADD WS-NUMA WS-NUMB WS-NUMC TO WS-NUMD GIVING WS-NUME. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUM3 : " WS-NUM3 DISPLAY "WS-NUM4 : " WS-NUM4 DISPLAY "WS-NUMA : " WS-NUMA DISPLAY "WS-NUMB : " WS-NUMB DISPLAY "WS-NUMC : " WS-NUMC DISPLAY "WS-NUMD : " WS-NUMD DISPLAY "WS-NUME : " WS-NUME STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 000000010 WS-NUM2 : 000000010 WS-NUM3 : 000000030 WS-NUM4 : 000000030 WS-NUMA : 000000010 WS-NUMB : 000000010 WS-NUMC : 000000010 WS-NUMD : 000000010 WS-NUME : 000000040
Subtract 动词
Subtract 动词用于减法运算。
语法
以下是 Subtract 运算的语法 -
SUBTRACT A B FROM C D SUBTRACT A B C FROM D GIVING E SUBTRACT CORR WS-GROUP1 TO WS-GROUP2
在语法-1 中,将 A 和 B 相加并从 C 中减去。结果存储在 C 中 (C = C-(A+B))。将 A 和 B 相加并从 D 中减去。结果存储在 D 中 (D = D-(A+B))。
在语法-2 中,将 A、B、C 相加并从 D 中减去。结果存储在 E 中 (E = D-(A+B+C))
在语法-3 中,将 WS-GROUP1 和 WS-GROUP2 中的子组项相减并将结果存储在 WS-GROUP2 中。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9) VALUE 10 . 01 WS-NUM2 PIC 9(9) VALUE 10. 01 WS-NUM3 PIC 9(9) VALUE 100. 01 WS-NUM4 PIC 9(9) VALUE 100. 01 WS-NUMA PIC 9(9) VALUE 10. 01 WS-NUMB PIC 9(9) VALUE 10. 01 WS-NUMC PIC 9(9) VALUE 10. 01 WS-NUMD PIC 9(9) VALUE 100. 01 WS-NUME PIC 9(9) VALUE 10. PROCEDURE DIVISION. SUBTRACT WS-NUM1 WS-NUM2 FROM WS-NUM3 WS-NUM4. SUBTRACT WS-NUMA WS-NUMB WS-NUMC FROM WS-NUMD GIVING WS-NUME. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUM3 : " WS-NUM3 DISPLAY "WS-NUM4 : " WS-NUM4 DISPLAY "WS-NUMA : " WS-NUMA DISPLAY "WS-NUMB : " WS-NUMB DISPLAY "WS-NUMC : " WS-NUMC DISPLAY "WS-NUMD : " WS-NUMD DISPLAY "WS-NUME : " WS-NUME STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 000000010 WS-NUM2 : 000000010 WS-NUM3 : 000000080 WS-NUM4 : 000000080 WS-NUMA : 000000010 WS-NUMB : 000000010 WS-NUMC : 000000010 WS-NUMD : 000000100 WS-NUME : 000000070
Multiply 动词
Multiply 动词用于乘法运算。
语法
以下是将两个或多个数字相乘的语法 -
MULTIPLY A BY B C MULTIPLY A BY B GIVING E
在语法-1 中,将 A 和 B 相乘并将结果存储在 B 中 (B=A*B)。将 A 和 C 相乘并将结果存储在 C 中 (C = A * C)。
在语法-2 中,将 A 和 B 相乘并将结果存储在 E 中 (E=A*B)。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9) VALUE 10 . 01 WS-NUM2 PIC 9(9) VALUE 10. 01 WS-NUM3 PIC 9(9) VALUE 10. 01 WS-NUMA PIC 9(9) VALUE 10. 01 WS-NUMB PIC 9(9) VALUE 10. 01 WS-NUMC PIC 9(9) VALUE 10. PROCEDURE DIVISION. MULTIPLY WS-NUM1 BY WS-NUM2 WS-NUM3. MULTIPLY WS-NUMA BY WS-NUMB GIVING WS-NUMC. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUM3 : " WS-NUM3 DISPLAY "WS-NUMA : " WS-NUMA DISPLAY "WS-NUMB : " WS-NUMB DISPLAY "WS-NUMC : " WS-NUMC STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 000000010 WS-NUM2 : 000000100 WS-NUM3 : 000000100 WS-NUMA : 000000010 WS-NUMB : 000000010 WS-NUMC : 000000100
Divide 动词
Divide 动词用于除法运算。
语法
以下是除法运算的语法 -
DIVIDE A INTO B DIVIDE A BY B GIVING C REMAINDER R
在语法-1 中,将 B 除以 A 并将结果存储在 B 中 (B=B/A)。
在语法-2 中,将 A 除以 B 并将结果存储在 C 中 (C=A/B),并将余数存储在 R 中。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9) VALUE 5. 01 WS-NUM2 PIC 9(9) VALUE 250. 01 WS-NUMA PIC 9(9) VALUE 100. 01 WS-NUMB PIC 9(9) VALUE 15. 01 WS-NUMC PIC 9(9). 01 WS-REM PIC 9(9). PROCEDURE DIVISION. DIVIDE WS-NUM1 INTO WS-NUM2. DIVIDE WS-NUMA BY WS-NUMB GIVING WS-NUMC REMAINDER WS-REM. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUMA : " WS-NUMA DISPLAY "WS-NUMB : " WS-NUMB DISPLAY "WS-NUMC : " WS-NUMC DISPLAY "WS-REM : " WS-REM STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 000000005 WS-NUM2 : 000000050 WS-NUMA : 000000100 WS-NUMB : 000000015 WS-NUMC : 000000006 WS-REM : 000000010
Compute 语句
Compute 语句用于在 COBOL 中编写算术表达式。这是 Add、Subtract、Multiply 和 Divide 的替代方法。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9) VALUE 10 . 01 WS-NUM2 PIC 9(9) VALUE 10. 01 WS-NUM3 PIC 9(9) VALUE 10. 01 WS-NUMA PIC 9(9) VALUE 50. 01 WS-NUMB PIC 9(9) VALUE 10. 01 WS-NUMC PIC 9(9). PROCEDURE DIVISION. COMPUTE WS-NUMC= (WS-NUM1 * WS-NUM2) - (WS-NUMA / WS-NUMB) + WS-NUM3. DISPLAY "WS-NUM1 : " WS-NUM1 DISPLAY "WS-NUM2 : " WS-NUM2 DISPLAY "WS-NUM3 : " WS-NUM3 DISPLAY "WS-NUMA : " WS-NUMA DISPLAY "WS-NUMB : " WS-NUMB DISPLAY "WS-NUMC : " WS-NUMC STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 : 000000010 WS-NUM2 : 000000010 WS-NUM3 : 000000010 WS-NUMA : 000000050 WS-NUMB : 000000010 WS-NUMC : 000000105
COBOL - 数据布局
COBOL 布局描述了每个字段的用途以及其中存在的值。以下是 COBOL 中使用的数据描述条目:
- 重新定义子句
- 重命名子句
- 用法子句
- 复制簿
重新定义子句
重新定义子句用于定义具有不同数据描述的存储。如果一个或多个数据项不同时使用,则相同的存储可用于另一个数据项。因此,可以使用不同的数据项引用相同的存储。
语法
以下是重新定义子句的语法:
01 WS-OLD PIC X(10). 01 WS-NEW1 REDEFINES WS-OLD PIC 9(8). 01 WS-NEW2 REDEFINES WS-OLD PIC A(10).
以下是所用参数的详细信息:
- WS-OLD 是重新定义项
- WS-NEW1 和 WS-NEW2 是重新定义项
重新定义项和重新定义项的级别号必须相同,并且不能为 66 或 88 级别号。不要将 VALUE 子句与重新定义项一起使用。在文件段中,不要将重新定义子句与 01 级别号一起使用。重新定义定义必须是您要重新定义的下一个数据描述。重新定义项的值始终与重新定义项相同。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-DESCRIPTION. 05 WS-DATE1 VALUE '20140831'. 10 WS-YEAR PIC X(4). 10 WS-MONTH PIC X(2). 10 WS-DATE PIC X(2). 05 WS-DATE2 REDEFINES WS-DATE1 PIC 9(8). PROCEDURE DIVISION. DISPLAY "WS-DATE1 : "WS-DATE1. DISPLAY "WS-DATE2 : "WS-DATE2. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
编译并执行上述程序时,将产生以下结果:
WS-DATE1 : 20140831 WS-DATE2 : 20140831
重命名子句
重命名子句用于为现有数据项提供不同的名称。它用于重新组合数据名称并为其提供新名称。新的数据名称可以在组或基本项之间重命名。级别号 66 保留用于重命名。
语法
以下是重命名子句的语法:
01 WS-OLD. 10 WS-A PIC 9(12). 10 WS-B PIC X(20). 10 WS-C PIC A(25). 10 WS-D PIC X(12). 66 WS-NEW RENAMES WS-A THRU WS-C.
仅在同一级别上才允许重命名。在上面的示例中,WS-A、WS-B 和 WS-C 处于同一级别。重命名定义必须是您要重命名的下一个数据描述。不要将重命名与 01、77 或 66 级别号一起使用。用于重命名的数据名称必须按顺序排列。具有出现子句的数据项不能重命名。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-DESCRIPTION. 05 WS-NUM. 10 WS-NUM1 PIC 9(2) VALUE 20. 10 WS-NUM2 PIC 9(2) VALUE 56. 05 WS-CHAR. 10 WS-CHAR1 PIC X(2) VALUE 'AA'. 10 WS-CHAR2 PIC X(2) VALUE 'BB'. 66 WS-RENAME RENAMES WS-NUM2 THRU WS-CHAR2. PROCEDURE DIVISION. DISPLAY "WS-RENAME : " WS-RENAME. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-RENAME : 56AABB
用法子句
用法子句指定存储格式数据的操作系统。它不能与级别号 66 或 88 一起使用。如果在组上指定了用法子句,则所有基本项将具有相同的用法子句。用法子句可用的不同选项如下:
显示
数据项以 ASCII 格式存储,每个字符占用 1 个字节。这是默认用法。
以下示例计算所需的字节数:
01 WS-NUM PIC S9(5)V9(3) USAGE IS DISPLAY. It requires 8 bytes as sign and decimal doesn't require any byte. 01 WS-NUM PIC 9(5) USAGE IS DISPLAY. It requires 5 bytes as sign.
计算/COMP
数据项以二进制格式存储。在这里,数据项必须是整数。
以下示例计算所需的字节数:
01 WS-NUM PIC S9(n) USAGE IS COMP. If 'n' = 1 to 4, it takes 2 bytes. If 'n' = 5 to 9, it takes 4 bytes. If 'n' = 10 to 18, it takes 8 bytes.
COMP-1
数据项类似于 Real 或 Float,并表示为单精度浮点数。在内部,数据以十六进制格式存储。COMP-1 不接受 PIC 子句。这里 1 个字等于 4 个字节。
COMP-2
数据项类似于 Long 或 Double,并表示为双精度浮点数。在内部,数据以十六进制格式存储。COMP-2 不指定 PIC 子句。这里 2 个字等于 8 个字节。
COMP-3
数据项以打包十进制格式存储。每个数字占用半个字节(1 个半字节),符号存储在最右边的半字节中。
以下示例计算所需的字节数:
01 WS-NUM PIC 9(n) USAGE IS COMP. Number of bytes = n/2 (If n is even) Number of bytes = n/2 + 1(If n is odd, consider only integer part) 01 WS-NUM PIC 9(4) USAGE IS COMP-3 VALUE 21. It requires 2 bytes of storage as each digit occupies half a byte. 01 WS-NUM PIC 9(5) USAGE IS COMP-3 VALUE 21. It requires 3 bytes of storage as each digit occupies half a byte.
复制簿
COBOL 复制簿是一段定义数据结构的代码。如果某个特定的数据结构在许多程序中使用,那么我们可以使用复制簿,而不是再次编写相同的数据结构。我们使用 COPY 语句将复制簿包含到程序中。COPY 语句用于工作存储段。
以下示例在 COBOL 程序中包含一个复制簿:
DATA DIVISION. WORKING-STORAGE SECTION. COPY ABC.
这里 ABC 是复制簿名称。ABC 复制簿中的以下数据项可以在程序内部使用。
01 WS-DESCRIPTION. 05 WS-NUM. 10 WS-NUM1 PIC 9(2) VALUE 20. 10 WS-NUM2 PIC 9(2) VALUE 56. 05 WS-CHAR. 10 WS-CHAR1 PIC X(2) VALUE 'AA'. 10 WS-CHAR2 PIC X(2) VALUE 'BB'.
COBOL - 条件语句
条件语句用于根据程序员指定的某些条件更改执行流程。条件语句始终计算为真或假。条件用于 IF、Evaluate 和 Perform 语句。条件的不同类型如下:
- IF 条件语句
- 关系条件
- 符号条件
- 类条件
- 条件名条件
- 否定条件
- 组合条件
IF 条件语句
IF 语句检查条件。如果条件为真,则执行 IF 块;如果条件为假,则执行 ELSE 块。
END-IF 用于结束 IF 块。要结束 IF 块,可以使用句点代替 END-IF。但对于多个 IF 块,始终建议使用 END-IF。
嵌套 IF - 出现在另一个 IF 块内部的 IF 块。嵌套 IF 语句的深度没有限制。
语法
以下是 IF 条件语句的语法:
IF [condition] THEN [COBOL statements] ELSE [COBOL statements] END-IF.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9). 01 WS-NUM2 PIC 9(9). 01 WS-NUM3 PIC 9(5). 01 WS-NUM4 PIC 9(6). PROCEDURE DIVISION. A000-FIRST-PARA. MOVE 25 TO WS-NUM1 WS-NUM3. MOVE 15 TO WS-NUM2 WS-NUM4. IF WS-NUM1 > WS-NUM2 THEN DISPLAY 'IN LOOP 1 - IF BLOCK' IF WS-NUM3 = WS-NUM4 THEN DISPLAY 'IN LOOP 2 - IF BLOCK' ELSE DISPLAY 'IN LOOP 2 - ELSE BLOCK' END-IF ELSE DISPLAY 'IN LOOP 1 - ELSE BLOCK' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
IN LOOP 1 - IF BLOCK IN LOOP 2 - ELSE BLOCK
关系条件
关系条件比较两个操作数,这两个操作数可以是标识符、文字或算术表达式。无论大小和用法子句如何,都会对数字字段进行代数比较。
对于非数字操作数
如果比较两个大小相等的非数字操作数,则从左到右比较字符,直到到达末尾。包含更多字符的操作数被声明为更大。
如果比较两个大小不相等的非数字操作数,则在较短的数据项的末尾附加空格,直到操作数的大小相等,然后根据前一点中提到的规则进行比较。
语法
以下是关系条件语句的语法:
[Data Name/Arithmetic Operation] [IS] [NOT] [Equal to (=),Greater than (>), Less than (<), Greater than or Equal (>=), Less than or equal (<=) ] [Data Name/Arithmetic Operation]
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(9). 01 WS-NUM2 PIC 9(9). PROCEDURE DIVISION. A000-FIRST-PARA. MOVE 25 TO WS-NUM1. MOVE 15 TO WS-NUM2. IF WS-NUM1 IS GREATER THAN OR EQUAL TO WS-NUM2 THEN DISPLAY 'WS-NUM1 IS GREATER THAN WS-NUM2' ELSE DISPLAY 'WS-NUM1 IS LESS THAN WS-NUM2' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
编译并执行上述程序时,将产生以下结果:
WS-NUM1 IS GREATER THAN WS-NUM2
符号条件
符号条件用于检查数字操作数的符号。它确定给定数字值是大于、小于还是等于零。
语法
以下是符号条件语句的语法:
[Data Name/Arithmetic Operation] [IS] [NOT] [Positive, Negative or Zero] [Data Name/Arithmetic Operation]
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC S9(9) VALUE -1234. 01 WS-NUM2 PIC S9(9) VALUE 123456. PROCEDURE DIVISION. A000-FIRST-PARA. IF WS-NUM1 IS POSITIVE THEN DISPLAY 'WS-NUM1 IS POSITIVE'. IF WS-NUM1 IS NEGATIVE THEN DISPLAY 'WS-NUM1 IS NEGATIVE'. IF WS-NUM1 IS ZERO THEN DISPLAY 'WS-NUM1 IS ZERO'. IF WS-NUM2 IS POSITIVE THEN DISPLAY 'WS-NUM2 IS POSITIVE'. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
编译并执行上述程序时,将产生以下结果:
WS-NUM1 IS NEGATIVE WS-NUM2 IS POSITIVE
类条件
类条件用于检查操作数是否仅包含字母或数字数据。空格在 ALPHABETIC、ALPHABETIC-LOWER 和 ALPHABETIC-UPPER 中被视为有效字符。
语法
以下是类条件语句的语法:
[Data Name/Arithmetic Operation>] [IS] [NOT] [NUMERIC, ALPHABETIC, ALPHABETIC-LOWER, ALPHABETIC-UPPER] [Data Name/Arithmetic Operation]
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC X(9) VALUE 'ABCD '. 01 WS-NUM2 PIC 9(9) VALUE 123456789. PROCEDURE DIVISION. A000-FIRST-PARA. IF WS-NUM1 IS ALPHABETIC THEN DISPLAY 'WS-NUM1 IS ALPHABETIC'. IF WS-NUM1 IS NUMERIC THEN DISPLAY 'WS-NUM1 IS NUMERIC'. IF WS-NUM2 IS NUMERIC THEN DISPLAY 'WS-NUM2 IS NUMERIC'. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-NUM1 IS ALPHABETIC WS-NUM2 IS NUMERIC
条件名条件
条件名是用户定义的名称。它包含用户指定的一组值。它的行为类似于布尔变量。它们使用级别号 88 定义。它不会有 PIC 子句。
语法
以下是用户定义条件语句的语法:
88 [Condition-Name] VALUE [IS, ARE] [LITERAL] [THRU LITERAL].
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM PIC 9(3). 88 PASS VALUES ARE 041 THRU 100. 88 FAIL VALUES ARE 000 THRU 40. PROCEDURE DIVISION. A000-FIRST-PARA. MOVE 65 TO WS-NUM. IF PASS DISPLAY 'Passed with ' WS-NUM ' marks'. IF FAIL DISPLAY 'FAILED with ' WS-NUM 'marks'. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Passed with 065 marks
否定条件
否定条件通过使用 NOT 关键字给出。如果条件为真,并且我们在其前面使用了 NOT,则其最终值为假。
语法
以下是否定条件语句的语法:
IF NOT [CONDITION] COBOL Statements END-IF.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(2) VALUE 20. 01 WS-NUM2 PIC 9(9) VALUE 25. PROCEDURE DIVISION. A000-FIRST-PARA. IF NOT WS-NUM1 IS LESS THAN WS-NUM2 THEN DISPLAY 'IF-BLOCK' ELSE DISPLAY 'ELSE-BLOCK' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
ELSE-BLOCK
组合条件
组合条件包含两个或多个使用逻辑运算符 AND 或 OR 连接的条件。
语法
以下是组合条件语句的语法:
IF [CONDITION] AND [CONDITION] COBOL Statements END-IF.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-NUM1 PIC 9(2) VALUE 20. 01 WS-NUM2 PIC 9(2) VALUE 25. 01 WS-NUM3 PIC 9(2) VALUE 20. PROCEDURE DIVISION. A000-FIRST-PARA. IF WS-NUM1 IS LESS THAN WS-NUM2 AND WS-NUM1=WS-NUM3 THEN DISPLAY 'Both condition OK' ELSE DISPLAY 'Error' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
Both condition OK
Evaluate 动词
Evaluate 动词是一系列 IF-ELSE 语句的替代。它可以用来评估多个条件。它类似于 C 程序中的 SWITCH 语句。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-A PIC 9 VALUE 0. PROCEDURE DIVISION. MOVE 3 TO WS-A. EVALUATE TRUE WHEN WS-A > 2 DISPLAY 'WS-A GREATER THAN 2' WHEN WS-A < 0 DISPLAY 'WS-A LESS THAN 0' WHEN OTHER DISPLAY 'INVALID VALUE OF WS-A' END-EVALUATE. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-A GREATER THAN 2
COBOL - 循环语句
有些任务需要反复执行,例如读取文件的每个记录直到文件结束。COBOL 中使用的循环语句有:
- 执行直到
- 执行直到
- 执行次数
- 执行变化
执行直到
执行直到用于通过按顺序给出第一个和最后一个段落名称来执行一系列段落。执行完最后一个段落后,控制权将返回。
内联执行
PERFORM 内部的语句将执行,直到到达 END-PERFORM。
语法
以下是内联执行的语法:
PERFORM DISPLAY 'HELLO WORLD' END-PERFORM.
非内联执行
在这里,一个语句在一个段落中执行,然后控制权转移到另一个段落或部分。
语法
以下是非内联执行的语法:
PERFORM PARAGRAPH1 THRU PARAGRAPH2
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. PROCEDURE DIVISION. A-PARA. PERFORM DISPLAY 'IN A-PARA' END-PERFORM. PERFORM C-PARA THRU E-PARA. B-PARA. DISPLAY 'IN B-PARA'. STOP RUN. C-PARA. DISPLAY 'IN C-PARA'. D-PARA. DISPLAY 'IN D-PARA'. E-PARA. DISPLAY 'IN E-PARA'.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
IN A-PARA IN C-PARA IN D-PARA IN E-PARA IN B-PARA
执行直到
在“执行直到”中,一个段落将执行,直到给定的条件变为真。“带前测试”是默认条件,它指示在执行段落中的语句之前检查条件。
语法
以下是执行直到的语法:
PERFORM A-PARA UNTIL COUNT=5 PERFORM A-PARA WITH TEST BEFORE UNTIL COUNT=5 PERFORM A-PARA WITH TEST AFTER UNTIL COUNT=5
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CNT PIC 9(1) VALUE 0. PROCEDURE DIVISION. A-PARA. PERFORM B-PARA WITH TEST AFTER UNTIL WS-CNT>3. STOP RUN. B-PARA. DISPLAY 'WS-CNT : 'WS-CNT. ADD 1 TO WS-CNT.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-CNT : 0 WS-CNT : 1 WS-CNT : 2 WS-CNT : 3
执行次数
在“执行次数”中,一个段落将执行指定的次数。
语法
以下是执行次数的语法:
PERFORM A-PARA 5 TIMES.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. PROCEDURE DIVISION. A-PARA. PERFORM B-PARA 3 TIMES. STOP RUN. B-PARA. DISPLAY 'IN B-PARA'.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
IN B-PARA IN B-PARA IN B-PARA
执行变化
在执行变化中,一个段落将执行,直到 Until 短语中的条件变为真。
语法
以下是执行变化的语法:
PERFORM A-PARA VARYING A FROM 1 BY 1 UNTIL A = 5.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-A PIC 9 VALUE 0. PROCEDURE DIVISION. A-PARA. PERFORM B-PARA VARYING WS-A FROM 1 BY 1 UNTIL WS-A=5 STOP RUN. B-PARA. DISPLAY 'IN B-PARA ' WS-A.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
IN B-PARA 1 IN B-PARA 2 IN B-PARA 3 IN B-PARA 4
GO TO 语句
GO TO 语句用于更改程序中的执行流程。在 GO TO 语句中,转移只能向前进行。它用于退出一个段落。使用的 GO TO 语句的不同类型如下:
无条件 GO TO
GO TO para-name.
条件 GO TO
GO TO para-1 para-2 para-3 DEPENDING ON x.
如果“x”等于 1,则控制权将转移到第一个段落;如果“x”等于 2,则控制权将转移到第二个段落,依此类推。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-A PIC 9 VALUE 2. PROCEDURE DIVISION. A-PARA. DISPLAY 'IN A-PARA' GO TO B-PARA. B-PARA. DISPLAY 'IN B-PARA '. GO TO C-PARA D-PARA DEPENDING ON WS-A. C-PARA. DISPLAY 'IN C-PARA '. D-PARA. DISPLAY 'IN D-PARA '. STOP RUN.
JCL 用于执行上述 COBOL 程序
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
编译并执行上述程序时,将产生以下结果
IN A-PARA IN B-PARA IN D-PARA
COBOL - 字符串处理
COBOL 中的字符串处理语句用于对字符串执行多种功能操作。以下是字符串处理语句:
- 检查
- 字符串
- 拆分字符串
检查
Inspect 动词用于计算或替换字符串中的字符。字符串操作可以对字母数字、数字或字母值执行。Inspect 操作从左到右执行。用于字符串操作的选项如下:
计数
计数选项用于计算字符串字符。
语法
以下是计数选项的语法:
INSPECT input-string TALLYING output-count FOR ALL CHARACTERS
使用的参数为:
- 输入字符串 - 要计算其字符的字符串。
- 输出计数 - 用于保存字符计数的数据项。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-CNT1 PIC 9(2) VALUE 0. 01 WS-CNT2 PIC 9(2) VALUE 0. 01 WS-STRING PIC X(15) VALUE 'ABCDACDADEAAAFF'. PROCEDURE DIVISION. INSPECT WS-STRING TALLYING WS-CNT1 FOR CHARACTER. DISPLAY "WS-CNT1 : "WS-CNT1. INSPECT WS-STRING TALLYING WS-CNT2 FOR ALL 'A'. DISPLAY "WS-CNT2 : "WS-CNT2 STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-CNT1 : 15 WS-CNT2 : 06
替换
替换选项用于替换字符串字符。
语法
以下是替换选项的语法:
INSPECT input-string REPLACING ALL char1 BY char2.
使用的参数为:
输入字符串 - 要从 char1 替换为 char2 的字符串的字符。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STRING PIC X(15) VALUE 'ABCDACDADEAAAFF'. PROCEDURE DIVISION. DISPLAY "OLD STRING : "WS-STRING. INSPECT WS-STRING REPLACING ALL 'A' BY 'X'. DISPLAY "NEW STRING : "WS-STRING. STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
OLD STRING : ABCDACDADEAAAFF NEW STRING : XBCDXCDXDEXXXFF
字符串
String 动词用于连接字符串。使用 STRING 语句,可以将两个或多个字符字符串组合成一个更长的字符串。“由...分隔”子句是强制性的。
语法
以下是 String 动词的语法:
STRING ws-string1 DELIMITED BY SPACE ws-string2 DELIMITED BY SIZE INTO ws-destination-string WITH POINTER ws-count ON OVERFLOW DISPLAY message1 NOT ON OVERFLOW DISPLAY message2 END-STRING.
以下是所用参数的详细信息:
- ws-string1 和 ws-string2:要连接的输入字符串
- ws-string:输出字符串
- ws-count:用于计算新连接字符串的长度
- 分隔符指定字符串的结尾
- 指针和溢出是可选的
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STRING PIC A(30). 01 WS-STR1 PIC A(15) VALUE 'Tutorialspoint'. 01 WS-STR2 PIC A(7) VALUE 'Welcome'. 01 WS-STR3 PIC A(7) VALUE 'To AND'. 01 WS-COUNT PIC 99 VALUE 1. PROCEDURE DIVISION. STRING WS-STR2 DELIMITED BY SIZE WS-STR3 DELIMITED BY SPACE WS-STR1 DELIMITED BY SIZE INTO WS-STRING WITH POINTER WS-COUNT ON OVERFLOW DISPLAY 'OVERFLOW!' END-STRING. DISPLAY 'WS-STRING : 'WS-STRING. DISPLAY 'WS-COUNT : 'WS-COUNT. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-STRING : WelcomeToTutorialspoint WS-COUNT : 25
拆分字符串
Unstring 动词用于将一个字符串拆分为多个子字符串。“由...分隔”子句是强制性的。
语法
以下是 Unstring 动词的语法:
UNSTRING ws-string DELIMITED BY SPACE INTO ws-str1, ws-str2 WITH POINTER ws-count ON OVERFLOW DISPLAY message NOT ON OVERFLOW DISPLAY message END-UNSTRING.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STRING PIC A(30) VALUE 'WELCOME TO TUTORIALSPOINT'. 01 WS-STR1 PIC A(7). 01 WS-STR2 PIC A(2). 01 WS-STR3 PIC A(15). 01 WS-COUNT PIC 99 VALUE 1. PROCEDURE DIVISION. UNSTRING WS-STRING DELIMITED BY SPACE INTO WS-STR1, WS-STR2, WS-STR3 END-UNSTRING. DISPLAY 'WS-STR1 : 'WS-STR1. DISPLAY 'WS-STR2 : 'WS-STR2. DISPLAY 'WS-STR3 : 'WS-STR3. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-STR1 : WELCOME WS-STR2 : TO WS-STR3 : TUTORIALSPOINT
COBOL - 表格处理
COBOL 中的数组称为表。数组是一种线性数据结构,是相同类型个别数据项的集合。表的数 据项在内部排序。
表声明
表在数据部分声明。Occurs 子句用于定义表。Occurs 子句指示数据名称定义的重复。它只能与从 02 到 49 开始的级别号一起使用。不要将 occurs 子句与 Redefines 一起使用。一维表和二维表的描述如下:
一维表
在一维表中,occurs 子句在声明中只使用一次。WSTABLE 是包含表的组项。WS-B 命名重复 10 次的表元素。
语法
以下是定义一维表的语法:
01 WS-TABLE. 05 WS-A PIC A(10) OCCURS 10 TIMES.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A PIC A(10) VALUE 'TUTORIALS' OCCURS 5 TIMES. PROCEDURE DIVISION. DISPLAY "ONE-D TABLE : "WS-TABLE. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
ONE-D TABLE : TUTORIALS TUTORIALS TUTORIALS TUTORIALS TUTORIALS
二维表
二维表是通过使两个数据元素都具有可变长度创建的。作为参考,请查看语法,然后尝试分析表。第一个数组 (WS-A) 可以重复 1 到 10 次,内部数组 (WS-C) 可以重复 1 到 5 次。对于 WS-A 的每个条目,将有相应的 5 个 WS-C 条目。
语法
以下是定义二维表的语法:
01 WS-TABLE. 05 WS-A OCCURS 10 TIMES. 10 WS-B PIC A(10). 10 WS-C OCCURS 5 TIMES. 15 WS-D PIC X(6).
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A OCCURS 2 TIMES. 10 WS-B PIC A(10) VALUE ' TUTORIALS'. 10 WS-C OCCURS 2 TIMES. 15 WS-D PIC X(6) VALUE ' POINT'. PROCEDURE DIVISION. DISPLAY "TWO-D TABLE : "WS-TABLE. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
TWO-D TABLE : TUTORIALS POINT POINT TUTORIALS POINT POINT
下标
可以使用下标访问表个别元素。下标值可以从 1 到表出现的次数。下标可以是任何正数。它不需要在数据部分进行任何声明。它会随着 occurs 子句自动创建。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A OCCURS 3 TIMES. 10 WS-B PIC A(2). 10 WS-C OCCURS 2 TIMES. 15 WS-D PIC X(3). PROCEDURE DIVISION. MOVE '12ABCDEF34GHIJKL56MNOPQR' TO WS-TABLE. DISPLAY 'WS-TABLE : ' WS-TABLE. DISPLAY 'WS-A(1) : ' WS-A(1). DISPLAY 'WS-C(1,1) : ' WS-C(1,1). DISPLAY 'WS-C(1,2) : ' WS-C(1,2). DISPLAY 'WS-A(2) : ' WS-A(2). DISPLAY 'WS-C(2,1) : ' WS-C(2,1). DISPLAY 'WS-C(2,2) : ' WS-C(2,2). DISPLAY 'WS-A(3) : ' WS-A(3). DISPLAY 'WS-C(3,1) : ' WS-C(3,1). DISPLAY 'WS-C(3,2) : ' WS-C(3,2). STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
WS-TABLE : 12ABCDEF34GHIJKL56MNOPQR WS-A(1) : 12ABCDEF WS-C(1,1) : ABC WS-C(1,2) : DEF WS-A(2) : 34GHIJKL WS-C(2,1) : GHI WS-C(2,2) : JKL WS-A(3) : 56MNOPQR WS-C(3,1) : MNO WS-C(3,2) : PQR
索引
也可以使用索引访问表元素。索引是从表开头到元素的位移。索引使用带 INDEXED BY 子句的 Occurs 子句声明。索引的值可以使用 SET 语句和 PERFORM Varying 选项更改。
语法
以下是定义表中索引的语法:
01 WS-TABLE. 05 WS-A PIC A(10) OCCURS 10 TIMES INDEXED BY I.
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A OCCURS 3 TIMES INDEXED BY I. 10 WS-B PIC A(2). 10 WS-C OCCURS 2 TIMES INDEXED BY J. 15 WS-D PIC X(3). PROCEDURE DIVISION. MOVE '12ABCDEF34GHIJKL56MNOPQR' TO WS-TABLE. PERFORM A-PARA VARYING I FROM 1 BY 1 UNTIL I >3 STOP RUN. A-PARA. PERFORM C-PARA VARYING J FROM 1 BY 1 UNTIL J>2. C-PARA. DISPLAY WS-C(I,J).
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
ABC DEF GHI JKL MNO PQR
Set 语句
Set语句用于更改索引值。Set动词用于初始化、增加或减少索引值。它与Search和Search All一起用于在表中定位元素。
语法
以下是使用Set语句的语法:
SET I J TO positive-number SET I TO J SET I TO 5 SET I J UP BY 1 SET J DOWN BY 5
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A OCCURS 3 TIMES INDEXED BY I. 10 WS-B PIC A(2). 10 WS-C OCCURS 2 TIMES INDEXED BY J. 15 WS-D PIC X(3). PROCEDURE DIVISION. MOVE '12ABCDEF34GHIJKL56MNOPQR' TO WS-TABLE. SET I J TO 1. DISPLAY WS-C(I,J). SET I J UP BY 1. DISPLAY WS-C(I,J). STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
ABC JKL
Search
Search是一种线性搜索方法,用于查找表内的元素。它可以对已排序和未排序的表执行。它仅用于由Index短语声明的表。它从索引的初始值开始。如果未找到要搜索的元素,则索引会自动增加1,并继续到表的末尾。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-A PIC X(1) OCCURS 18 TIMES INDEXED BY I. 01 WS-SRCH PIC A(1) VALUE 'M'. PROCEDURE DIVISION. MOVE 'ABCDEFGHIJKLMNOPQR' TO WS-TABLE. SET I TO 1. SEARCH WS-A AT END DISPLAY 'M NOT FOUND IN TABLE' WHEN WS-A(I) = WS-SRCH DISPLAY 'LETTER M FOUND IN TABLE' END-SEARCH. STOP RUN.
执行上述 COBOL 程序的**JCL**。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
LETTER M FOUND IN TABLE
Search All
Search All是一种二分搜索方法,用于查找表内的元素。对于Search All选项,表必须按排序顺序排列。索引不需要初始化。在二分搜索中,表被分成两半,并确定要搜索的元素位于哪一半。此过程重复,直到找到元素或到达末尾。
示例
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-RECORD OCCURS 10 TIMES ASCENDING KEY IS WS-NUM INDEXED BY I. 10 WS-NUM PIC 9(2). 10 WS-NAME PIC A(3). PROCEDURE DIVISION. MOVE '12ABC56DEF34GHI78JKL93MNO11PQR' TO WS-TABLE. SEARCH ALL WS-RECORD AT END DISPLAY 'RECORD NOT FOUND' WHEN WS-NUM(I) = 93 DISPLAY 'RECORD FOUND ' DISPLAY WS-NUM(I) DISPLAY WS-NAME(I) END-SEARCH.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO
当您编译并执行上述程序时,它会生成以下结果:
RECORD FOUND 93 MNO
COBOL - 文件处理
COBOL中的文件概念与C/C++中的不同。在学习COBOL中“文件”的基础知识时,不应将两种语言的概念关联起来。简单的文本文件不能在COBOL中使用,而是使用PS(物理顺序)和VSAM文件。本模块将讨论PS文件。
要理解COBOL中的文件处理,必须了解基本术语。这些术语仅用于理解文件处理的基础知识。在“文件处理动词”一章中将进一步讨论更深入的术语。以下是基本术语:
- 字段
- 记录
- 物理记录
- 逻辑记录
- 文件
以下示例有助于理解这些术语:
字段
字段用于指示存储关于元素的数据。它表示单个元素,如上例所示,例如学生ID、姓名、分数、总分和百分比。任何字段中的字符数称为字段大小,例如,学生姓名可以有10个字符。字段可以具有以下属性:
主键是每个记录中唯一的字段,用于识别特定记录。例如,在学生成绩文件中,每个学生将具有唯一的学生ID,构成主键。
外键是唯一或非唯一字段,用于搜索相关数据。例如,在学生成绩文件中,当不知道学生ID时,可以使用学生的全名作为外键。
描述符字段用于描述实体。例如,在学生成绩文件中,分数和百分比字段为记录添加含义,被称为描述符。
记录
记录是用于描述实体的一组字段。一个或多个字段一起形成一个记录。例如,在学生成绩文件中,学生ID、姓名、分数、总分和百分比构成一个记录。记录中所有字段的累积大小称为记录大小。文件中存在的记录可以是固定长度或可变长度的。
物理记录
物理记录是存在于外部设备上的信息。它也称为块。
逻辑记录
逻辑记录是程序使用信息。在COBOL程序中,一次只能处理一个记录,称为逻辑记录。
文件
文件是相关记录的集合。例如,学生成绩文件包含所有学生的记录。
COBOL - 文件组织
文件组织指示记录如何在文件中组织。文件有不同类型的组织,以提高访问记录的效率。以下是文件组织方案的类型:
- 顺序文件组织
- 索引顺序文件组织
- 相对文件组织
本模块中提到的语法及其各自的术语仅指它们在程序中的用法。使用这些语法的完整程序将在“文件处理动词”一章中讨论。
顺序文件组织
顺序文件包含按顺序存储和访问的记录。以下是顺序文件组织的关键属性:
记录可以按顺序读取。要读取第10条记录,必须先读取所有之前的9条记录。
记录按顺序写入。不能在中间插入新记录。新记录始终插入到文件的末尾。
将记录放入顺序文件后,无法删除、缩短或延长记录。
记录的顺序一旦插入,就永远无法更改。
可以更新记录。如果新记录长度与旧记录长度相同,则可以覆盖记录。
顺序输出文件是打印的良好选择。
语法
以下是顺序文件组织的语法:
INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name-jcl ORGANIZATION IS SEQUENTIAL
索引顺序文件组织
索引顺序文件包含可以顺序访问的记录。也可以进行直接访问。它包含两个部分:
数据文件包含按顺序排列的记录。
索引文件包含主键及其在数据文件中的地址。
以下是顺序文件组织的关键属性:
记录可以按顺序读取,就像在顺序文件组织中一样。
如果知道主键,则可以随机访问记录。索引文件用于获取记录的地址,然后从数据文件中获取记录。
在此文件系统中维护排序索引,该索引将键值与记录在文件中的位置相关联。
还可以创建备用索引以获取记录。
语法
以下是索引顺序文件组织的语法:
INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name-jcl ORGANIZATION IS INDEXED RECORD KEY IS primary-key ALTERNATE RECORD KEY IS rec-key
相对文件组织
相对文件包含按其相对地址排序的记录。以下是相对文件组织的关键属性:
记录可以按顺序读取,就像在顺序和索引文件组织中一样。
可以使用相对键访问记录。相对键表示记录相对于文件起始地址的位置。
可以使用相对键插入记录。相对地址是使用相对键计算的。
相对文件提供对记录的最快访问。
此文件系统的主要缺点是,如果缺少一些中间记录,它们也会占用空间。
语法
以下是相对文件组织的语法:
INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name-jcl ORGANIZATION IS RELATIVE RELATIVE KEY IS rec-key
COBOL - 文件访问模式
到目前为止,已经讨论了文件组织方案。对于每种文件组织方案,都可以使用不同的访问模式。以下是文件访问模式的类型:
- 顺序访问
- 随机访问
- 动态访问
本模块中提到的语法及其各自的术语仅指它们在程序中的用法。使用这些语法的完整程序将在下一章中讨论。
顺序访问
当访问模式为顺序时,记录检索方法会根据所选的文件组织而改变。
对于顺序文件,记录按插入的相同顺序访问。
对于索引文件,用于获取记录的参数是记录键值。
对于相对文件,相对记录键用于检索记录。
语法
以下是顺序访问模式的语法:
ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS SEQUENTIAL ACCESS MODE IS SEQUENTIAL ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS INDEXED ACCESS MODE IS SEQUENTIAL RECORD KEY IS rec-key1 ALTERNATE RECORD KEY IS rec-key2 ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS RELATIVE ACCESS MODE IS SEQUENTIAL RELATIVE KEY IS rec-key1
随机访问
当访问模式为RANDOM时,记录检索方法会根据所选的文件组织而改变。
对于索引文件,记录根据放置在键字段中的值进行访问,该键字段可以是主键或备用键。可以存在一个或多个备用索引。
对于相对文件,记录通过相对记录键检索。
语法
以下是随机访问模式的语法:
ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS INDEXED ACCESS MODE IS RANDOM RECORD KEY IS rec-key1 ALTERNATE RECORD KEY IS rec-key2 ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS RELATIVE ACCESS MODE IS RANDOM RELATIVE KEY IS rec-key1
动态访问
动态访问在同一个程序中支持顺序和随机访问。使用动态访问,一个文件定义用于执行顺序和随机处理,例如按顺序访问某些记录,并按其键访问其他记录。
对于相对文件和索引文件,动态访问模式允许您在读取文件时在顺序访问模式和随机访问模式之间来回切换,方法是在READ语句上使用NEXT短语。NEXT和READ功能将在下一章中讨论。
语法
以下是动态访问模式的语法:
ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS SEQUENTIAL ACCESS MODE IS DYNAMIC RECORD KEY IS rec-key1 ALTERNATE RECORD KEY IS rec-key2 ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT file-name ASSIGN TO dd-name ORGANIZATION IS RELATIVE ACCESS MODE IS DYNAMIC RELATIVE KEY IS rec-key1
COBOL - 文件处理动词
文件处理动词用于对文件执行各种操作。以下是文件处理动词:
- Open
- Read
- Write
- Rewrite
- Delete
- Start
- Close
Open动词
Open是必须执行的第一个文件操作。如果Open成功,则只有其他操作才能在文件上执行。只有在打开文件后,文件结构中的变量才能用于处理。每个文件操作后都会更新FILE STATUS变量。
语法
OPEN "mode" file-name.
这里,file-name是字符串文字,您将使用它来命名您的文件。文件可以以下列模式打开:
序号 | 模式和描述 |
---|---|
1 |
Input Input模式用于现有文件。在此模式下,我们只能读取文件,不允许对文件执行任何其他操作。 |
2 |
Output Output模式用于在文件中插入记录。如果使用顺序文件并且文件包含某些记录,则首先会删除现有记录,然后在新文件中插入新记录。对于索引文件或相对文件,情况并非如此。 |
3 |
Extend Extend模式用于在顺序文件中追加记录。在此模式下,记录将插入到末尾。如果文件访问模式为Random或Dynamic,则不能使用Extend模式。 |
4 |
I-O Input-Output模式用于读取和重写文件记录。 |
Read动词
READ动词用于读取文件记录。READ的功能是从文件中获取记录。在每个READ动词处,只能将一条记录读入文件结构中。要执行读取操作,请以INPUT或I-O模式打开文件。在每个READ语句处,文件指针都会递增,因此会读取连续的记录。
语法
以下是当文件访问模式为顺序时读取记录的语法:
READ file-name NEXT RECORD INTO ws-file-structure AT END DISPLAY 'End of File' NOT AT END DISPLAY 'Record Details:' ws-file-structure END-READ.
以下是使用的参数:
NEXT RECORD是可选的,并在顺序读取索引顺序文件时指定。
INTO子句是可选的。ws-file-structure在WorkingStorage节中定义,以从READ语句获取值。
当到达文件末尾时,AT END条件变为True。
示例:以下示例使用行顺序组织读取现有文件。可以使用Live Demo选项编译和执行此程序,它将显示文件中存在的所有记录。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STUDENT ASSIGN TO 'input.txt' ORGANIZATION IS LINE SEQUENTIAL. DATA DIVISION. FILE SECTION. FD STUDENT. 01 STUDENT-FILE. 05 STUDENT-ID PIC 9(5). 05 NAME PIC A(25). WORKING-STORAGE SECTION. 01 WS-STUDENT. 05 WS-STUDENT-ID PIC 9(5). 05 WS-NAME PIC A(25). 01 WS-EOF PIC A(1). PROCEDURE DIVISION. OPEN INPUT STUDENT. PERFORM UNTIL WS-EOF='Y' READ STUDENT INTO WS-STUDENT AT END MOVE 'Y' TO WS-EOF NOT AT END DISPLAY WS-STUDENT END-READ END-PERFORM. CLOSE STUDENT. STOP RUN.
假设input.txt文件中提供的输入文件数据包含以下内容:
20003 Mohtashim M. 20004 Nishant Malik 20005 Amitabh Bachhan
当您编译并执行上述程序时,它会生成以下结果:
20003 Mohtashim M. 20004 Nishant Malik 20005 Amitabh Bachhan
语法
以下是当文件访问模式为随机时读取记录的语法:
READ file-name RECORD INTO ws-file-structure KEY IS rec-key INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'Record Details: ' ws-file-structure END-READ.
示例:以下示例使用索引组织读取现有文件。可以使用大型机的JCL编译和执行此程序,它将显示文件中存在的所有记录。在大机服务器上,我们不使用文本文件,而是使用PS文件。
假设大型机上的文件与上述示例中input.txt文件的内容相同。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STUDENT ASSIGN TO IN1 ORGANIZATION IS INDEXED ACCESS IS RANDOM RECORD KEY IS STUDENT-ID FILE STATUS IS FS. DATA DIVISION. FILE SECTION. FD STUDENT. 01 STUDENT-FILE. 05 STUDENT-ID PIC 9(5). 05 NAME PIC A(25). WORKING-STORAGE SECTION. 01 WS-STUDENT. 05 WS-STUDENT-ID PIC 9(5). 05 WS-NAME PIC A(25). PROCEDURE DIVISION. OPEN INPUT STUDENT. MOVE 20005 TO STUDENT-ID. READ STUDENT RECORD INTO WS-STUDENT-FILE KEY IS STUDENT-ID INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY WS-STUDENT-FILE END-READ. CLOSE STUDENT. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //IN1 DD DSN = STUDENT-FILE-NAME,DISP=SHR
当您编译并执行上述程序时,它会生成以下结果:
20005 Amitabh Bachhan
WRITE动词
WRITE动词用于在文件中插入记录。写入记录后,它将不再在记录缓冲区中可用。在将记录插入文件之前,请将值移动到记录缓冲区,然后执行WRITE动词。
WRITE语句可以与FROM选项一起使用,以直接从工作存储变量写入记录。From是一个可选子句。如果访问模式为顺序,则要写入记录,文件必须以Output模式或Extend模式打开。如果访问模式为随机或动态,则要写入记录,文件必须以Output模式或I-O模式打开。
语法
以下是当文件组织为顺序时读取记录的语法:
WRITE record-buffer [FROM ws-file-structure] END-WRITE.
以下是当文件组织为索引或相对时读取记录的语法:
WRITE record-buffer [FROM ws-file-structure] INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'Record Inserted' END-WRITE.
示例:以下示例显示了当组织为顺序时如何在新文件中插入新记录。
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STUDENT ASSIGN TO OUT1 ORGANIZATION IS SEQUENTIAL ACCESS IS SEQUENTIAL FILE STATUS IS FS. DATA DIVISION. FILE SECTION. FD STUDENT 01 STUDENT-FILE. 05 STUDENT-ID PIC 9(5). 05 NAME PIC A(25). 05 CLASS PIC X(3). WORKING-STORAGE SECTION. 01 WS-STUDENT. 05 WS-STUDENT-ID PIC 9(5). 05 WS-NAME PIC A(25). 05 WS-CLASS PIC X(3). PROCEDURE DIVISION. OPEN EXTEND STUDENT. MOVE 1000 TO STUDENT-ID. MOVE 'Tim' TO NAME. MOVE '10' TO CLASS. WRITE STUDENT-FILE END-WRITE. CLOSE STUDENT. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //OUT1 DD DSN = OUTPUT-FILE-NAME,DISP = (NEW,CATALOG,DELETE)
编译并执行上述程序后,它将向输出文件添加一条新记录。
1000 Tim 10
REWRITE动词
REWRITE动词用于更新记录。文件应以I-O模式打开以进行重写操作。它只能在成功执行READ操作后使用。REWRITE动词会覆盖最后读取的记录。
语法
以下是当文件组织为顺序时读取记录的语法:
REWRITE record-buffer [FROM ws-file-structure] END-REWRITE.
以下是当文件组织为索引或相对时读取记录的语法:
REWRITE record-buffer [FROM ws-file-structure] INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'Record Updated' END-REWRITE.
示例:以下示例显示了如何更新我们在之前的WRITE步骤中插入的现有记录:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STUDENT ASSIGN TO IN1 ORGANIZATION IS INDEXED ACCESS IS RANDOM RECORD KEY IS STUDENT-ID FILE STATUS IS FS. DATA DIVISION. FILE SECTION. FD STUDENT 01 STUDENT-FILE. 05 STUDENT-ID PIC 9(4). 05 NAME PIC A(12). 05 CLASS PIC X(3). WORKING-STORAGE SECTION. 01 WS-STUDENT. 05 WS-STUDENT-ID PIC 9(5). 05 WS-NAME PIC A(25). 05 WS-CLASS PIC X(3). PROCEDURE DIVISION. OPEN I-O STUDENT. MOVE '1000' TO STUDENT-ID. READ STUDENT KEY IS STUDENT-ID INVALID KEY DISPLAY ‘KEY IS NOT EXISTING’ END-READ. MOVE 'Tim Dumais' TO NAME. REWRITE STUDENT-FILE END-REWRITE. CLOSE STUDENT. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //IN1 DD DSN = OUTPUT-FILE-NAME,DISP = SHR
编译并执行上述程序后,它将更新记录:
1000 Tim Dumais 10
DELETE动词
DELETE动词只能对索引文件和相对文件执行。文件必须以I-O模式打开。在顺序文件组织中,无法删除记录。在顺序访问模式下,将删除READ语句最后读取的记录。在随机访问模式下,指定记录键,然后执行DELETE操作。
语法
以下是删除记录的语法:
DELETE file-name RECORD INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'Record Deleted' END-DELETE.
示例:删除现有记录:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STUDENT ASSIGN TO OUT1 ORGANIZATION IS INDEXED ACCESS IS RANDOM RECORD KEY IS STUDENT-ID FILE STATUS IS FS. DATA DIVISION. FILE SECTION. FD STUDENT 01 STUDENT-FILE. 05 STUDENT-ID PIC 9(4). 05 NAME PIC A(12). 05 CLASS PIC X(3). WORKING-STORAGE SECTION. 01 WS-STUDENT. 05 WS-STUDENT-ID PIC 9(5). 05 WS-NAME PIC A(25). 05 WS-CLASS PIC X(3). PROCEDURE DIVISION. OPEN I-O STUDENT. MOVE '1000' TO STUDENT-ID. DELETE STUDENT RECORD INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'Record Deleted' END-DELETE. CLOSE STUDENT. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //OUT1 DD DSN = OUTPUT-FILE-NAME,DISP = SHR
当您编译并执行上述程序时,它会生成以下结果:
Record Deleted
START动词
START动词只能对索引文件和相对文件执行。它用于将文件指针置于特定记录处。访问模式必须为顺序或动态。文件必须以I-O或Input模式打开。
语法
以下是将指针置于特定记录处的语法:
START file-name KEY IS [=, >, <, NOT, <= or >=] rec-key INVALID KEY DISPLAY 'Invalid Key' NOT INVALID KEY DISPLAY 'File Pointer Updated' END-START.
CLOSE动词
CLOSE动词用于关闭文件。执行CLOSE操作后,文件结构中的变量将不可用于处理。程序和文件之间的链接将丢失。
语法
以下是关闭文件的语法:
CLOSE file-name.
COBOL - 子程序
Cobol子程序是可以独立编译但不能独立执行的程序。子程序有两种类型:内部子程序,如Perform语句,和外部子程序,如CALL动词。
CALL动词
CALL动词用于将控制权从一个程序转移到另一个程序。包含CALL动词的程序称为调用程序,被调用的程序称为被调用程序。调用程序的执行将暂停,直到被调用程序完成执行。Exit Program语句用于在被调用程序中将控制权转移回。
被调用程序约束
以下是被调用程序的要求:
Linkage节必须在被调用程序中定义。它包含在程序中传递的数据元素。数据项不应具有Value子句。PIC子句必须与通过调用程序传递的变量兼容。
Procedure division using包含从调用程序传递的变量列表,并且顺序必须与Call动词中提到的顺序相同。
Exit program语句用于在被调用程序中将控制权转移回。它必须是被调用程序中的最后一个语句。
参数可以通过两种方式在程序之间传递:
- 按引用
- 按内容
按引用调用
如果被调用程序中变量的值被修改,则它们的新值将反映在调用程序中。如果没有指定BY子句,则变量始终按引用传递。
语法
以下是按引用调用子程序的语法:
CALL sub-prog-name USING variable-1, variable-2.
示例
以下示例是MAIN调用程序,UTIL是被调用程序:
IDENTIFICATION DIVISION. PROGRAM-ID. MAIN. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STUDENT-ID PIC 9(4) VALUE 1000. 01 WS-STUDENT-NAME PIC A(15) VALUE 'Tim'. PROCEDURE DIVISION. CALL 'UTIL' USING WS-STUDENT-ID, WS-STUDENT-NAME. DISPLAY 'Student Id : ' WS-STUDENT-ID DISPLAY 'Student Name : ' WS-STUDENT-NAME STOP RUN.
被调用程序
IDENTIFICATION DIVISION. PROGRAM-ID. UTIL. DATA DIVISION. LINKAGE SECTION. 01 LS-STUDENT-ID PIC 9(4). 01 LS-STUDENT-NAME PIC A(15). PROCEDURE DIVISION USING LS-STUDENT-ID, LS-STUDENT-NAME. DISPLAY 'In Called Program'. MOVE 1111 TO LS-STUDENT-ID. EXIT PROGRAM.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = MAIN
当您编译并执行上述程序时,它会生成以下结果:
In Called Program Student Id : 1111 Student Name : Tim
按内容调用
如果被调用程序中变量的值被修改,则它们的新值将不会反映在调用程序中。
语法
以下是按内容调用子程序的语法:
CALL sub-prog-name USING BY CONTENT variable-1, BY CONTENT variable-2.
示例
以下示例是MAIN调用程序,UTIL是被调用程序:
IDENTIFICATION DIVISION. PROGRAM-ID. MAIN. DATA DIVISION. WORKING-STORAGE SECTION. 01 WS-STUDENT-ID PIC 9(4) VALUE 1000. 01 WS-STUDENT-NAME PIC A(15) VALUE 'Tim'. PROCEDURE DIVISION. CALL 'UTIL' USING BY CONTENT WS-STUDENT-ID, BY CONTENT WS-STUDENT-NAME. DISPLAY 'Student Id : ' WS-STUDENT-ID DISPLAY 'Student Name : ' WS-STUDENT-NAME STOP RUN.
被调用程序
IDENTIFICATION DIVISION. PROGRAM-ID. UTIL. DATA DIVISION. LINKAGE SECTION. 01 LS-STUDENT-ID PIC 9(4). 01 LS-STUDENT-NAME PIC A(15). PROCEDURE DIVISION USING LS-STUDENT-ID, LS-STUDENT-NAME. DISPLAY 'In Called Program'. MOVE 1111 TO LS-STUDENT-ID. EXIT PROGRAM.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = MAIN
当您编译并执行上述程序时,它会生成以下结果:
In Called Program Student Id : 1000 Student Name : Tim
调用类型
调用有两种类型:
静态调用发生在使用NODYNAM编译器选项编译程序时。静态调用的程序在编译时加载到存储器中。
动态调用发生在使用DYNAM和NODLL编译器选项编译程序时。动态调用的程序在运行时加载到存储器中。
COBOL - 内部排序
对文件中的数据进行排序或合并两个或多个文件是几乎所有面向业务的应用程序中常见的必要操作。排序用于按升序或降序排列记录,以便可以执行顺序处理。COBOL中使用两种用于文件排序的技术:
外部排序用于通过在JCL中使用SORT实用程序对文件进行排序。我们在JCL章节中讨论过这一点。目前,我们将重点关注内部排序。
内部排序用于在COBOL程序中对文件进行排序。SORT动词用于对文件进行排序。
SORT动词
COBOL中的排序过程使用三个文件:
输入文件是要按升序或降序排序的文件。
工作文件用于在排序过程中保存记录。输入文件记录被传输到工作文件以进行排序过程。此文件应在SD条目下的File-Section中定义。
输出文件是排序过程结束后获得的文件。它是SORT动词的最终输出。
语法
以下是排序文件的语法:
SORT work-file ON ASCENDING KEY rec-key1 [ON DESCENDING KEY rec-key2] USING input-file GIVING output-file.
SORT执行以下操作:
以I-O模式打开work-file,以INPUT模式打开input-file,以OUTPUT模式打开output-file。
将input-file中存在的记录传输到work-file。
按rec-key以升序/降序对SORT-FILE进行排序。
将排序后的记录从work-file传输到output-file。
关闭input-file和output-file,并删除work-file。
示例
在以下示例中,INPUT是需要按升序排序的输入文件:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INPUT ASSIGN TO IN. SELECT OUTPUT ASSIGN TO OUT. SELECT WORK ASSIGN TO WRK. DATA DIVISION. FILE SECTION. FD INPUT. 01 INPUT-STUDENT. 05 STUDENT-ID-I PIC 9(5). 05 STUDENT-NAME-I PIC A(25). FD OUTPUT. 01 OUTPUT-STUDENT. 05 STUDENT-ID-O PIC 9(5). 05 STUDENT-NAME-O PIC A(25). SD WORK. 01 WORK-STUDENT. 05 STUDENT-ID-W PIC 9(5). 05 STUDENT-NAME-W PIC A(25). PROCEDURE DIVISION. SORT WORK ON ASCENDING KEY STUDENT-ID-O USING INPUT GIVING OUTPUT. DISPLAY 'Sort Successful'. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //IN DD DSN = INPUT-FILE-NAME,DISP = SHR //OUT DD DSN = OUTPUT-FILE-NAME,DISP = SHR //WRK DD DSN = &&TEMP
当您编译并执行上述程序时,它会生成以下结果:
Sort Successful
MERGE动词
使用MERGE语句合并两个或多个具有相同顺序的文件。合并过程中使用的文件:
- 输入文件:Input-1、Input-2
- 工作文件
- 输出文件
语法
以下是合并两个或多个文件的语法:
MERGE work-file ON ASCENDING KEY rec-key1 [ON DESCENDING KEY rec-key2] USING input-1, input-2 GIVING output-file.
MERGE执行以下操作:
以I-O模式打开work-file,以INPUT模式打开input-files,以OUTPUT模式打开output-file。
将input-files中存在的记录传输到work-file。
按rec-key以升序/降序对SORT-FILE进行排序。
将排序后的记录从work-file传输到output-file。
关闭input-file和output-file,并删除work-file。
示例
在以下示例中,INPUT1和INPUT2是要按升序合并的输入文件:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INPUT1 ASSIGN TO IN1. SELECT INPUT2 ASSIGN TO IN2. SELECT OUTPUT ASSIGN TO OUT. SELECT WORK ASSIGN TO WRK. DATA DIVISION. FILE SECTION. FD INPUT1. 01 INPUT1-STUDENT. 05 STUDENT-ID-I1 PIC 9(5). 05 STUDENT-NAME-I1 PIC A(25). FD INPUT2. 01 INPUT2-STUDENT. 05 STUDENT-ID-I2 PIC 9(5). 05 STUDENT-NAME-I2 PIC A(25). FD OUTPUT. 01 OUTPUT-STUDENT. 05 STUDENT-ID-O PIC 9(5). 05 STUDENT-NAME-O PIC A(25). SD WORK. 01 WORK-STUDENT. 05 STUDENT-ID-W PIC 9(5). 05 STUDENT-NAME-W PIC A(25). PROCEDURE DIVISION. MERGE WORK ON ASCENDING KEY STUDENT-ID-O USING INPUT1, INPUT2 GIVING OUTPUT. DISPLAY 'Merge Successful'. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP1 EXEC PGM = HELLO //IN1 DD DSN=INPUT1-FILE-NAME,DISP=SHR //IN2 DD DSN=INPUT2-FILE-NAME,DISP=SHR //OUT DD DSN = OUTPUT-FILE-NAME,DISP=SHR //WRK DD DSN = &&TEMP
当您编译并执行上述程序时,它会生成以下结果:
Merge Successful
COBOL - 数据库接口
到目前为止,我们已经学习了在COBOL中使用文件的方法。现在,我们将讨论COBOL程序如何与DB2交互。它涉及以下术语:
- 嵌入式SQL
- DB2应用程序编程
- 主机变量
- SQLCA
- SQL查询
- 游标
嵌入式SQL
嵌入式SQL语句用于在COBOL程序中执行标准SQL操作。在编译应用程序程序之前,SQL处理器会预处理嵌入式SQL语句。COBOL被称为主机语言。COBOL-DB2应用程序是包含COBOL和DB2的应用程序。
嵌入式SQL语句的工作方式与普通SQL语句类似,但有一些细微的差别。例如,查询的输出将定向到一组预定义的变量,这些变量称为主机变量。在SELECT语句中添加了一个INTO子句。
DB2应用程序编程
以下是编写COBOL-DB2程序时需要遵循的规则:
所有SQL语句必须用EXEC SQL和ENDEXEC分隔。
SQL语句必须在Area B中编码。
程序中使用的所有表都必须在WorkingStorage节中声明。这是通过使用INCLUDE语句完成的。
除INCLUDE和DECLARE TABLE之外的所有SQL语句都必须出现在Procedure Division中。
主机变量
主机变量用于接收来自表的數據或在表中插入数据。必须为要在程序和DB2之间传递的所有值声明主机变量。它们在Working-Storage节中声明。
主机变量不能是组项,但可以组合在主机结构中。它们不能被Renamed或Redefined。在SQL语句中使用主机变量时,在它们前面加上冒号 (:)。
语法
以下是声明主机变量并在Working-Storage节中包含表的语法:
DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE table-name END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 STUDENT-REC. 05 STUDENT-ID PIC 9(4). 05 STUDENT-NAME PIC X(25). 05 STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC.
SQLCA
SQLCA 是一个 SQL 通信区域,DB2 通过它将 SQL 执行的反馈传递给程序。它告诉程序执行是否成功。SQLCA 下面有一些预定义的变量,例如包含错误代码的 **SQLCODE**。SQLCODE 中的值“000”表示执行成功。
语法
以下是如何在 Working-Storage 部分声明 SQLCA 的语法:
DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC.
SQL查询
假设我们有一个名为“Student”的表,其中包含学生 ID、学生姓名和学生地址。
STUDENT 表包含以下数据:
Student Id Student Name Student Address 1001 Mohtashim M. Hyderabad 1002 Nishant Malik Delhi 1003 Amitabh Bachan Mumbai 1004 Chulbul Pandey Lucknow
以下示例演示了如何在 COBOL 程序中使用 **SELECT** 查询:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE STUDENT END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 WS-STUDENT-REC. 05 WS-STUDENT-ID PIC 9(4). 05 WS-STUDENT-NAME PIC X(25). 05 WS-STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. EXEC SQL SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS FROM STUDENT WHERE STUDENT-ID=1004 END-EXEC. IF SQLCODE = 0 DISPLAY WS-STUDENT-RECORD ELSE DISPLAY 'Error' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP001 EXEC PGM = IKJEFT01 //STEPLIB DD DSN = MYDATA.URMI.DBRMLIB,DISP = SHR //SYSPRINT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //SYSOUT DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(HELLO) PLAN(PLANNAME) - END /*
当您编译并执行上述程序时,它会生成以下结果:
1004 Chulbul Pandey Lucknow
以下示例演示了如何在 COBOL 程序中使用 **INSERT** 查询:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE STUDENT END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 WS-STUDENT-REC. 05 WS-STUDENT-ID PIC 9(4). 05 WS-STUDENT-NAME PIC X(25). 05 WS-STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. MOVE 1005 TO WS-STUDENT-ID. MOVE 'TutorialsPoint' TO WS-STUDENT-NAME. MOVE 'Hyderabad' TO WS-STUDENT-ADDRESS. EXEC SQL INSERT INTO STUDENT(STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS) VALUES (:WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS) END-EXEC. IF SQLCODE = 0 DISPLAY 'Record Inserted Successfully' DISPLAY WS-STUDENT-REC ELSE DISPLAY 'Error' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP001 EXEC PGM = IKJEFT01 //STEPLIB DD DSN = MYDATA.URMI.DBRMLIB,DISP=SHR //SYSPRINT DD SYSOUT = * //SYSUDUMP DD SYSOUT = * //SYSOUT DD SYSOUT = * //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(HELLO) PLAN(PLANNAME) - END /*
当您编译并执行上述程序时,它会生成以下结果:
Record Inserted Successfully 1005 TutorialsPoint Hyderabad
以下示例演示了如何在 COBOL 程序中使用 **UPDATE** 查询:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE STUDENT END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 WS-STUDENT-REC. 05 WS-STUDENT-ID PIC 9(4). 05 WS-STUDENT-NAME PIC X(25). 05 WS-STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. MOVE 'Bangalore' TO WS-STUDENT-ADDRESS. EXEC SQL UPDATE STUDENT SET STUDENT-ADDRESS=:WS-STUDENT-ADDRESS WHERE STUDENT-ID = 1003 END-EXEC. IF SQLCODE = 0 DISPLAY 'Record Updated Successfully' ELSE DISPLAY 'Error' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP001 EXEC PGM = IKJEFT01 //STEPLIB DD DSN = MYDATA.URMI.DBRMLIB,DISP = SHR //SYSPRINT DD SYSOUT = * //SYSUDUMP DD SYSOUT = * //SYSOUT DD SYSOUT = * //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(HELLO) PLAN(PLANNAME) - END /*
当您编译并执行上述程序时,它会生成以下结果:
Record Updated Successfully
以下 **示例** 演示了如何在 COBOL 程序中使用 **DELETE** 查询:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE STUDENT END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 WS-STUDENT-REC. 05 WS-STUDENT-ID PIC 9(4). 05 WS-STUDENT-NAME PIC X(25). 05 WS-STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. MOVE 1005 TO WS-STUDENT-ID. EXEC SQL DELETE FROM STUDENT WHERE STUDENT-ID=:WS-STUDENT-ID END-EXEC. IF SQLCODE = 0 DISPLAY 'Record Deleted Successfully' ELSE DISPLAY 'Error' END-IF. STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP001 EXEC PGM = IKJEFT01 //STEPLIB DD DSN = MYDATA.URMI.DBRMLIB,DISP=SHR //SYSPRINT DD SYSOUT = * //SYSUDUMP DD SYSOUT = * //SYSOUT DD SYSOUT = * //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(HELLO) PLAN(PLANNAME) - END /*
当您编译并执行上述程序时,它会生成以下结果:
Record Deleted Successfully
游标
游标用于一次处理多行选择。它们是保存查询所有结果的数据结构。它们可以在 Working-Storage 部分或 Procedure Division 中定义。以下是与游标相关的操作:
- 声明
- Open
- Close
- 获取
声明游标
游标声明可以在 Working-Storage 部分或 Procedure Division 中完成。第一个语句是 DECLARE 语句,这是一个非可执行语句。
EXEC SQL DECLARE STUDCUR CURSOR FOR SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENT WHERE STUDENT-ID >:WS-STUDENT-ID END-EXEC.
Open
在使用游标之前,必须执行 Open 语句。Open 语句准备 SELECT 以供执行。
EXEC SQL OPEN STUDCUR END-EXEC.
Close
Close 语句释放游标占用的所有内存。在结束程序之前关闭游标是强制性的。
EXEC SQL CLOSE STUDCUR END-EXEC.
获取
Fetch 语句标识游标并将值放入 INTO 子句中。Fetch 语句在循环中编码,因为我们一次获取一行。
EXEC SQL FETCH STUDCUR INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS END-EXEC.
以下示例演示了如何使用游标从 STUDENT 表中获取所有记录:
IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE STUDENT END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 WS-STUDENT-REC. 05 WS-STUDENT-ID PIC 9(4). 05 WS-STUDENT-NAME PIC X(25). 05 WS-STUDENT-ADDRESS X(50). EXEC SQL END DECLARE SECTION END-EXEC. EXEC SQL DECLARE STUDCUR CURSOR FOR SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENT WHERE STUDENT-ID >:WS-STUDENT-ID END-EXEC. PROCEDURE DIVISION. MOVE 1001 TO WS-STUDENT-ID. PERFORM UNTIL SQLCODE = 100 EXEC SQL FETCH STUDCUR INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS END-EXEC DISPLAY WS-STUDENT-REC END-PERFORM STOP RUN.
执行上述 COBOL 程序的JCL:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS = A,MSGCLASS = C //STEP001 EXEC PGM=IKJEFT01 //STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR //SYSPRINT DD SYSOUT=* //SYSUDUMP DD SYSOUT=* //SYSOUT DD SYSOUT=* //SYSTSIN DD * DSN SYSTEM(SSID) RUN PROGRAM(HELLO) PLAN(PLANNAME) - END /*
当您编译并执行上述程序时,它会生成以下结果:
1001 Mohtashim M. Hyderabad 1002 Nishant Malik Delhi 1003 Amitabh Bachan Mumbai 1004 Chulbul Pandey Lucknow