如何编写 cobol 代码来执行以下逻辑?
How to write a cobol code to do the below logic?
1) 读取一行 2000 个字符,并将所有空格替换为单个“+”加号字符。即,将 "A B"
转换为 "A+B"
或将 "A B"
转换为 "A+B"
2)读取一行2000个字符,然后搜索特定的模式,如"PWD"或"INI"等,最后将接下来的6个字符存储到一个变量中。
3) 读取一行2000个字符并将字符串中的最后一个单词存储到一个变量中。
编辑:
我使用 Micro Focus COBOL。
This 是我这段代码的截图。
我的代码如下。它删除了一些空格,但不是全部。尝试用随机数的空格写任何句子,输入文件中的单词和测试数据。
IDENTIFICATION DIVISION.
PROGRAM-ID. SALAUT.
ENVIRONMENT DIVISION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO "INFILE"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-IN-FILE-STATUS.
SELECT OUT-FILE ASSIGN TO "OUTFILE"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-OUT-FILE-STATUS.
DATA DIVISION.
FILE SECTION.
FD IN-FILE.
01 FS-IN-FILE PIC X(200).
FD OUT-FILE.
01 FS-OUT-FILE PIC X(200).
WORKING-STORAGE SECTION.
01 WS-ATMA-C.
03 WS-OUT-FILE-STATUS PIC X(02).
03 WS-IN-FILE-STATUS PIC X(02).
03 WS-LOOP-COUNTER PIC 9(03) VALUE 1.
03 WS-IN-EOF PIC X value 'N'.
03 WS-IN-FILE-LEN PIC 9(03).
03 WS-IN-SPACE-CNT PIC 9(03) VALUE 1.
03 FS-IN-FILE-2 PIC X(200).
03 WS-TRIL-SPACE-CNT PIC 9(03).
03 WS-TOT-SPACE-CNT PIC 9(03).
PROCEDURE DIVISION.
MAIN-PARA.
OPEN INPUT IN-FILE.
IF WS-IN-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-OPEN-ERROR : STOP-RUN'
EXHIBIT NAMED WS-IN-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
OPEN OUTPUT OUT-FILE.
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'OUT-FILE-OPEN-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
PERFORM SPACE-REMOVER-PARA THRU SPACE-REMOVER-PARA-EXIT.
CLOSE IN-FILE.
IF WS-IN-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-CLOSE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-IN-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
CLOSE OUT-FILE.
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-CLOSE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
MAIN-PARA-EXIT.
STOP RUN.
SPACE-REMOVER-PARA.
PERFORM UNTIL WS-IN-EOF = 'Y'
INITIALIZE FS-IN-FILE FS-OUT-FILE WS-IN-FILE-LEN FS-IN-FILE-2
READ IN-FILE
AT END
MOVE 'Y' TO WS-IN-EOF
NOT AT END
INSPECT FS-IN-FILE TALLYING WS-IN-FILE-LEN FOR CHARACTERS
EXHIBIT NAMED WS-IN-FILE-LEN
MOVE 1 TO WS-LOOP-COUNTER
IF WS-IN-FILE-LEN <> 0
PERFORM UNTIL WS-IN-SPACE-CNT <= ZEROS
INSPECT FS-IN-FILE TALLYING WS-TOT-SPACE-CNT FOR ALL " "
INSPECT FUNCTION REVERSE (FS-IN-FILE) TALLYING
WS-TRIL-SPACE-CNT FOR LEADING " "
INITIALIZE WS-IN-SPACE-CNT
COMPUTE WS-IN-SPACE-CNT =
WS-TOT-SPACE-CNT - WS-TRIL-SPACE-CNT
PERFORM VARYING WS-LOOP-COUNTER FROM 1 BY 1
UNTIL WS-LOOP-COUNTER >=
WS-IN-FILE-LEN - (2 * WS-TRIL-SPACE-CNT)
IF FS-IN-FILE(WS-LOOP-COUNTER:2) = " "
STRING FS-IN-FILE(1:WS-LOOP-COUNTER - 1) DELIMITED BY SIZE
FS-IN-FILE(WS-LOOP-COUNTER + 2
: WS-IN-FILE-LEN - WS-LOOP-COUNTER - 2)
DELIMITED BY SIZE
INTO FS-IN-FILE-2
END-STRING
INITIALIZE FS-IN-FILE
MOVE FS-IN-FILE-2 TO FS-IN-FILE
INITIALIZE FS-IN-FILE-2
END-IF
END-PERFORM
INITIALIZE WS-LOOP-COUNTER WS-TRIL-SPACE-CNT WS-TOT-SPACE-CNT
END-PERFORM
WRITE FS-OUT-FILE FROM FS-IN-FILE
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'OUT-FILE-WRITE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF
END-IF
END-READ
END-PERFORM.
SPACE-REMOVER-PARA-EXIT.
EXIT.
因为INSPECT REPLACING
只允许替换相同数量的字节你不能使用它。正如 Brian 指出的那样,您的 COBOL 运行时可能带有 GnuCOBOL 的 FUNCTION SUBSTITUTE
等选项。无论如何,问题 "Which COBOL" 仍然需要回答。
要执行 Thraydor 的方法,请使用 UNSTRING
到 table 使用字符串指针。有事
MOVE 1 TO strpoint
PERFORM VARYING table-idx FROM 1 BY 1
UNTIL table-idx = table-max
UNSTRING your2000line DELIMITED BY ALL SPACES
INTO tmp-table (table-idx)
WITH POINTER strpoint
NOT ON OVERFLOW
EXIT PERFORM
END-UNSTRING
END-PERFORM
另一种总是有效的方法是在 2000 个字节上使用一堆 IF your2000line (pos:1)
语句(如果可能:将其合并为一个 EVALUATE
)通过检查字节来进行简单的 PERFORM
字节(比较最后一个字节以删除重复字节)将带有替换的源传输到临时字段并MOVE
完成后将其返回
请编辑您的问题以显示您尝试过的内容,这样您可以获得更好的答案。
首先,请记住 COBOL 是一种方言语言。还有针对 1974、1985、2002(现已过时,2014 年合并)和 2014 标准的活跃商业编译器。所有这些都有自己的语言扩展,在不同的 COBOL 编译器中可能会或很多不会被尊重。
如果您的学习目标是针对特定环境(您说过的 IBM Mainframe COBOL),那么将该方言用作您正在使用的实际 COBOL 中可用内容的子集。这意味着使用 IBM 手册。
不要仅仅因为它在当时看起来是个好主意就从地方挑选东西并使用它。
我不得不承认 EXHIBIT 使用起来非常有趣,但它只是一种语言扩展,IBM 至少在 OS/VS COBOL 的后期版本中放弃了它。它和 ON 一样,是一个 "debugging" 语句,尽管这并没有阻止它们被使用 "normally"。在简单的 DISPLAY 上使用 EXHIBIT 会产生额外的开销。 IBM Enterprise COBOL 只有一个简单的 DISPLAY。
虽然您可能认为使用象形图(试图拔出自己头发的人物的 "oh my goodness, what symbol should I use for this")很有趣,但请注意该特定符号是 2014 年标准的后来者,如果它出现在接下来的 20 到 50 年内在 Enterprise COBOL 中,我会感到惊讶(要做的事情很少,另一种可爱的写法 "not equal to" 当许多 already 存在时,COBOL 甚至还有一个 ELSE)。
一些建议。如果它所做的本身就是 "everything-including-install-a-new-kitchen-sink",则不要有一个名为 "remove-all-the-spaces" 的过程。难怪您找不到它不起作用的原因吗?
很多很多COBOL程序都有读取文件的任务,直到结束,然后处理文件中的记录。首先让自己成为那些工作良好的人之一。这与程序正在寻址的 "business process" 相关吗?不,这只是技术性的东西,你离不开它所以把它藏在某个地方。在哪里?在已执行的程序中(段落或部分)。不要指望那些很快想知道你的程序在做什么的人会想要阅读每个程序所做的事情。隐藏它。
您可以在这里找到很多关于编写 COBOL 程序的一般性建议。注意那些建议使用 full-stops/periods、启动读取和 COBOL 程序的一般结构的内容。
准确描述事物非常重要。为数据名称和过程起一个好的、描述性的、准确的名称。文件是记录的集合。
您已经缩减了数据的大小以使测试更容易,但没有意识到当您返回完整数据时您的数据定义有问题。你的 "counters" 只能容纳三位数,当他们需要能够处理最多 2000 的数字时。
对一段数据做一些事情,然后立即用与原始数据没有任何关系的其他数据压缩该数据是没有意义的。
MOVE SPACE TO B
MOVE A TO B
第一个 MOVE 是多余的、多余的,只会浪费 CPU 时间并混淆程序的下一个 reader。 "Is there some code missing, because otherwise that's just plain dumb".
这是使用 MOVE 的示例的变体,您到处都在这样做:
INITIALIZE WS-IN-SPACE-CNT
COMPUTE WS-IN-SPACE-CNT =
WS-TOT-SPACE-CNT - WS-TRIL-SPACE-CNT
INITIALIZE 是一种浪费 space、资源、引入混乱和额外的代码行,使您的程序更难理解。
还有,用过的东西不要"reset",这样就"ready for next time"了。这会产生依赖性,这是您程序的未来修改者不会期望的。即使 expected/noticed,它们也会让代码更难理解。
如果不知道您认为代码有什么问题,就不可能确切地说出您的代码有什么问题。例如,甚至没有用“+”替换任何 space 的符号,所以如果您认为这是错误的地方,那么您根本就没有为它编码。
您也只尝试了三项任务中的一项。如果您认为其中有一个不工作是错误的...
知道自己的想法是错误的是一回事,还有很多其他的问题。如果您坐下来有条不紊地整理它们,那么您会想出一个 "structurally" COBOL 程序,您会发现它更容易理解您自己的代码的作用以及问题所在。
A B C D E
A+B+C+D+E
要使用 STRING 从第一个到第二个,请查看 Simon 使用 WITH POINTER 的建议。
您可以采用的另一种方法是使用引用修改。
无论哪种方式,您都将一次构建一个结果字段
This field intentionally blank
A
A+B
A+B+C
A+B+C+D
A+B+C+D+E
而不是每次都把所有的数据都扔来扔去。还有其他编码方式,但可以留待以后使用。
1) 读取一行 2000 个字符,并将所有空格替换为单个“+”加号字符。即,将 "A B"
转换为 "A+B"
或将 "A B"
转换为 "A+B"
2)读取一行2000个字符,然后搜索特定的模式,如"PWD"或"INI"等,最后将接下来的6个字符存储到一个变量中。
3) 读取一行2000个字符并将字符串中的最后一个单词存储到一个变量中。
编辑: 我使用 Micro Focus COBOL。
This 是我这段代码的截图。
我的代码如下。它删除了一些空格,但不是全部。尝试用随机数的空格写任何句子,输入文件中的单词和测试数据。
IDENTIFICATION DIVISION.
PROGRAM-ID. SALAUT.
ENVIRONMENT DIVISION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO "INFILE"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-IN-FILE-STATUS.
SELECT OUT-FILE ASSIGN TO "OUTFILE"
ORGANIZATION IS LINE SEQUENTIAL
FILE STATUS IS WS-OUT-FILE-STATUS.
DATA DIVISION.
FILE SECTION.
FD IN-FILE.
01 FS-IN-FILE PIC X(200).
FD OUT-FILE.
01 FS-OUT-FILE PIC X(200).
WORKING-STORAGE SECTION.
01 WS-ATMA-C.
03 WS-OUT-FILE-STATUS PIC X(02).
03 WS-IN-FILE-STATUS PIC X(02).
03 WS-LOOP-COUNTER PIC 9(03) VALUE 1.
03 WS-IN-EOF PIC X value 'N'.
03 WS-IN-FILE-LEN PIC 9(03).
03 WS-IN-SPACE-CNT PIC 9(03) VALUE 1.
03 FS-IN-FILE-2 PIC X(200).
03 WS-TRIL-SPACE-CNT PIC 9(03).
03 WS-TOT-SPACE-CNT PIC 9(03).
PROCEDURE DIVISION.
MAIN-PARA.
OPEN INPUT IN-FILE.
IF WS-IN-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-OPEN-ERROR : STOP-RUN'
EXHIBIT NAMED WS-IN-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
OPEN OUTPUT OUT-FILE.
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'OUT-FILE-OPEN-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
PERFORM SPACE-REMOVER-PARA THRU SPACE-REMOVER-PARA-EXIT.
CLOSE IN-FILE.
IF WS-IN-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-CLOSE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-IN-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
CLOSE OUT-FILE.
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'IN-FILE-CLOSE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF.
MAIN-PARA-EXIT.
STOP RUN.
SPACE-REMOVER-PARA.
PERFORM UNTIL WS-IN-EOF = 'Y'
INITIALIZE FS-IN-FILE FS-OUT-FILE WS-IN-FILE-LEN FS-IN-FILE-2
READ IN-FILE
AT END
MOVE 'Y' TO WS-IN-EOF
NOT AT END
INSPECT FS-IN-FILE TALLYING WS-IN-FILE-LEN FOR CHARACTERS
EXHIBIT NAMED WS-IN-FILE-LEN
MOVE 1 TO WS-LOOP-COUNTER
IF WS-IN-FILE-LEN <> 0
PERFORM UNTIL WS-IN-SPACE-CNT <= ZEROS
INSPECT FS-IN-FILE TALLYING WS-TOT-SPACE-CNT FOR ALL " "
INSPECT FUNCTION REVERSE (FS-IN-FILE) TALLYING
WS-TRIL-SPACE-CNT FOR LEADING " "
INITIALIZE WS-IN-SPACE-CNT
COMPUTE WS-IN-SPACE-CNT =
WS-TOT-SPACE-CNT - WS-TRIL-SPACE-CNT
PERFORM VARYING WS-LOOP-COUNTER FROM 1 BY 1
UNTIL WS-LOOP-COUNTER >=
WS-IN-FILE-LEN - (2 * WS-TRIL-SPACE-CNT)
IF FS-IN-FILE(WS-LOOP-COUNTER:2) = " "
STRING FS-IN-FILE(1:WS-LOOP-COUNTER - 1) DELIMITED BY SIZE
FS-IN-FILE(WS-LOOP-COUNTER + 2
: WS-IN-FILE-LEN - WS-LOOP-COUNTER - 2)
DELIMITED BY SIZE
INTO FS-IN-FILE-2
END-STRING
INITIALIZE FS-IN-FILE
MOVE FS-IN-FILE-2 TO FS-IN-FILE
INITIALIZE FS-IN-FILE-2
END-IF
END-PERFORM
INITIALIZE WS-LOOP-COUNTER WS-TRIL-SPACE-CNT WS-TOT-SPACE-CNT
END-PERFORM
WRITE FS-OUT-FILE FROM FS-IN-FILE
IF WS-OUT-FILE-STATUS <> '00'
EXHIBIT 'OUT-FILE-WRITE-ERROR : STOP-RUN'
EXHIBIT NAMED WS-OUT-FILE-STATUS
PERFORM MAIN-PARA-EXIT
END-IF
END-IF
END-READ
END-PERFORM.
SPACE-REMOVER-PARA-EXIT.
EXIT.
因为INSPECT REPLACING
只允许替换相同数量的字节你不能使用它。正如 Brian 指出的那样,您的 COBOL 运行时可能带有 GnuCOBOL 的 FUNCTION SUBSTITUTE
等选项。无论如何,问题 "Which COBOL" 仍然需要回答。
要执行 Thraydor 的方法,请使用 UNSTRING
到 table 使用字符串指针。有事
MOVE 1 TO strpoint
PERFORM VARYING table-idx FROM 1 BY 1
UNTIL table-idx = table-max
UNSTRING your2000line DELIMITED BY ALL SPACES
INTO tmp-table (table-idx)
WITH POINTER strpoint
NOT ON OVERFLOW
EXIT PERFORM
END-UNSTRING
END-PERFORM
另一种总是有效的方法是在 2000 个字节上使用一堆 IF your2000line (pos:1)
语句(如果可能:将其合并为一个 EVALUATE
)通过检查字节来进行简单的 PERFORM
字节(比较最后一个字节以删除重复字节)将带有替换的源传输到临时字段并MOVE
完成后将其返回
请编辑您的问题以显示您尝试过的内容,这样您可以获得更好的答案。
首先,请记住 COBOL 是一种方言语言。还有针对 1974、1985、2002(现已过时,2014 年合并)和 2014 标准的活跃商业编译器。所有这些都有自己的语言扩展,在不同的 COBOL 编译器中可能会或很多不会被尊重。
如果您的学习目标是针对特定环境(您说过的 IBM Mainframe COBOL),那么将该方言用作您正在使用的实际 COBOL 中可用内容的子集。这意味着使用 IBM 手册。
不要仅仅因为它在当时看起来是个好主意就从地方挑选东西并使用它。
我不得不承认 EXHIBIT 使用起来非常有趣,但它只是一种语言扩展,IBM 至少在 OS/VS COBOL 的后期版本中放弃了它。它和 ON 一样,是一个 "debugging" 语句,尽管这并没有阻止它们被使用 "normally"。在简单的 DISPLAY 上使用 EXHIBIT 会产生额外的开销。 IBM Enterprise COBOL 只有一个简单的 DISPLAY。
虽然您可能认为使用象形图(试图拔出自己头发的人物的 "oh my goodness, what symbol should I use for this")很有趣,但请注意该特定符号是 2014 年标准的后来者,如果它出现在接下来的 20 到 50 年内在 Enterprise COBOL 中,我会感到惊讶(要做的事情很少,另一种可爱的写法 "not equal to" 当许多 already 存在时,COBOL 甚至还有一个 ELSE)。
一些建议。如果它所做的本身就是 "everything-including-install-a-new-kitchen-sink",则不要有一个名为 "remove-all-the-spaces" 的过程。难怪您找不到它不起作用的原因吗?
很多很多COBOL程序都有读取文件的任务,直到结束,然后处理文件中的记录。首先让自己成为那些工作良好的人之一。这与程序正在寻址的 "business process" 相关吗?不,这只是技术性的东西,你离不开它所以把它藏在某个地方。在哪里?在已执行的程序中(段落或部分)。不要指望那些很快想知道你的程序在做什么的人会想要阅读每个程序所做的事情。隐藏它。
您可以在这里找到很多关于编写 COBOL 程序的一般性建议。注意那些建议使用 full-stops/periods、启动读取和 COBOL 程序的一般结构的内容。
准确描述事物非常重要。为数据名称和过程起一个好的、描述性的、准确的名称。文件是记录的集合。
您已经缩减了数据的大小以使测试更容易,但没有意识到当您返回完整数据时您的数据定义有问题。你的 "counters" 只能容纳三位数,当他们需要能够处理最多 2000 的数字时。
对一段数据做一些事情,然后立即用与原始数据没有任何关系的其他数据压缩该数据是没有意义的。
MOVE SPACE TO B
MOVE A TO B
第一个 MOVE 是多余的、多余的,只会浪费 CPU 时间并混淆程序的下一个 reader。 "Is there some code missing, because otherwise that's just plain dumb".
这是使用 MOVE 的示例的变体,您到处都在这样做:
INITIALIZE WS-IN-SPACE-CNT
COMPUTE WS-IN-SPACE-CNT =
WS-TOT-SPACE-CNT - WS-TRIL-SPACE-CNT
INITIALIZE 是一种浪费 space、资源、引入混乱和额外的代码行,使您的程序更难理解。
还有,用过的东西不要"reset",这样就"ready for next time"了。这会产生依赖性,这是您程序的未来修改者不会期望的。即使 expected/noticed,它们也会让代码更难理解。
如果不知道您认为代码有什么问题,就不可能确切地说出您的代码有什么问题。例如,甚至没有用“+”替换任何 space 的符号,所以如果您认为这是错误的地方,那么您根本就没有为它编码。
您也只尝试了三项任务中的一项。如果您认为其中有一个不工作是错误的...
知道自己的想法是错误的是一回事,还有很多其他的问题。如果您坐下来有条不紊地整理它们,那么您会想出一个 "structurally" COBOL 程序,您会发现它更容易理解您自己的代码的作用以及问题所在。
A B C D E
A+B+C+D+E
要使用 STRING 从第一个到第二个,请查看 Simon 使用 WITH POINTER 的建议。
您可以采用的另一种方法是使用引用修改。
无论哪种方式,您都将一次构建一个结果字段
This field intentionally blank
A
A+B
A+B+C
A+B+C+D
A+B+C+D+E
而不是每次都把所有的数据都扔来扔去。还有其他编码方式,但可以留待以后使用。