标准COBOL中如何用动态分配变量存储完整文件内容?
问题描述
我正在学习COBOL,尝试用C风格的文件IO(每次读取x字节)读取无格式文件。目前能逐个字节读取并即时显示单个字符,但无法把文件内容存储到变量里。
尝试的代码
IDENTIFICATION DIVISION. PROGRAM-ID. FILEREADER. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT FILE-TO-READ ASSIGN USING INPUT-FILE-NAME ORGANIZATION IS SEQUENTIAL ACCESS IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD FILE-TO-READ. 01 CHAR PIC X(1). WORKING-STORAGE SECTION. 01 FILE-DATA-POINTER USAGE IS POINTER. 01 FILE-DATA-HOLDER PIC X BASED. 01 INPUT-DATA. 05 INPUT-FILE-NAME PIC X(100). 05 INPUT-FILE-CHARACTERS PIC 9(18). 01 MISC-DATA. 05 EOF PIC X(1). 05 STRING-INDEX PIC 9(18) USAGE IS COMP. PROCEDURE DIVISION. MAIN. PERFORM GET-INPUT. PERFORM ALLOCATE-STORAGE. PERFORM READ-FILE. PERFORM DISPLAY-FILE. PERFORM CLEAN-UP. STOP RUN. GET-INPUT. DISPLAY "Please enter the name of the file (maximum 100 characters)." ACCEPT INPUT-FILE-NAME. DISPLAY "Please enter the number of characters in your file (the number of bytes)." ACCEPT INPUT-FILE-CHARACTERS. ALLOCATE-STORAGE. ALLOCATE INPUT-FILE-CHARACTERS CHARACTERS RETURNING FILE-DATA-POINTER SET ADDRESS OF FILE-DATA-HOLDER TO FILE-DATA-POINTER. IF ADDRESS OF FILE-DATA-POINTER = NULL DISPLAY "System error when allocating RAM. Exiting..." STOP RUN END-IF. READ-FILE. INITIALIZE STRING-INDEX. MOVE 'N' TO EOF. MOVE 1 TO STRING-INDEX. OPEN INPUT FILE-TO-READ. PERFORM UNTIL EOF = 'Y' READ FILE-TO-READ AT END MOVE 'Y' TO EOF NOT AT END MOVE CHAR TO FILE-DATA-HOLDER (STRING-INDEX:1) ADD 1 TO STRING-INDEX END-READ END-PERFORM. CLOSE FILE-TO-READ. DISPLAY-FILE. DISPLAY FILE-DATA-HOLDER. CLEAN-UP. FREE FILE-DATA-POINTER.
编译警告
file_reader.cbl:64: warning: suspicious reference-modification: always using max. length [-Wothers] 62 | READ FILE-TO-READ 63 | AT END MOVE 'Y' TO EOF 64 > NOT AT END MOVE CHAR TO FILE-DATA-HOLDER 65 | (STRING-INDEX:1)
程序输出
Please enter the name of the file (maximum 100 characters). test.txt <------ User input Please enter the number of characters in your file (the number of bytes). 4 <------ Also user input L
注:测试文件内容为ASCII编码的"Lorem Ipsum"。
调研过程
一开始以为是COBOL字符串不能像C/Python那样下标索引,尝试用字符数组(表)替代,但发现COBOL无法动态分配表,于是回到原点。后来发现问题不是下标索引,而是FILE-DATA-HOLDER的长度只有1个字符。
解决方案
要在标准COBOL中用动态分配变量存储整个文件内容,关键是正确利用指针访问分配的存储区域,同时跟踪有效长度。以下是修改后的代码及说明:
修改后的代码
IDENTIFICATION DIVISION. PROGRAM-ID. FILEREADER. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT FILE-TO-READ ASSIGN USING INPUT-FILE-NAME ORGANIZATION IS SEQUENTIAL ACCESS IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD FILE-TO-READ. 01 CHAR PIC X(1). WORKING-STORAGE SECTION. 01 FILE-DATA-POINTER USAGE IS POINTER. *> 基于指针的单字符变量,用于通过引用修改访问任意存储位置 01 FILE-DATA-BASED PIC X BASED. 01 INPUT-DATA. 05 INPUT-FILE-NAME PIC X(100). 05 INPUT-FILE-CHARACTERS PIC 9(18) USAGE COMP. 01 MISC-DATA. 05 EOF PIC X(1) VALUE 'N'. 05 STRING-INDEX PIC 9(18) USAGE COMP VALUE 1. *> 跟踪分配的总长度,避免越界访问 01 ALLOCATED-LENGTH PIC 9(18) USAGE COMP. PROCEDURE DIVISION. MAIN. PERFORM GET-INPUT. PERFORM ALLOCATE-STORAGE. PERFORM READ-FILE. PERFORM DISPLAY-FILE. PERFORM CLEAN-UP. STOP RUN. GET-INPUT. DISPLAY "Please enter the name of the file (maximum 100 characters)." ACCEPT INPUT-FILE-NAME. *> 去除文件名尾部空格,避免文件找不到 INSPECT INPUT-FILE-NAME TAILING SPACES REPLACING BY ''. DISPLAY "Please enter the number of characters in your file (the number of bytes)." ACCEPT INPUT-FILE-CHARACTERS. MOVE INPUT-FILE-CHARACTERS TO ALLOCATED-LENGTH. ALLOCATE-STORAGE. ALLOCATE ALLOCATED-LENGTH CHARACTERS RETURNING FILE-DATA-POINTER. SET ADDRESS OF FILE-DATA-BASED TO FILE-DATA-POINTER. IF FILE-DATA-POINTER = NULL DISPLAY "System error when allocating RAM. Exiting..." STOP RUN END-IF. READ-FILE. OPEN INPUT FILE-TO-READ. *> 增加长度判断,防止越界写入 PERFORM UNTIL EOF = 'Y' OR STRING-INDEX > ALLOCATED-LENGTH READ FILE-TO-READ AT END MOVE 'Y' TO EOF NOT AT END *> 通过引用修改,将字符写入指针指向的对应位置 MOVE CHAR TO FILE-DATA-BASED (STRING-INDEX:1) ADD 1 TO STRING-INDEX END-READ END-PERFORM. CLOSE FILE-TO-READ. *> 若提前遇到EOF,更新实际存储的有效长度 IF EOF = 'Y' SUBTRACT 1 FROM STRING-INDEX MOVE STRING-INDEX TO ALLOCATED-LENGTH END-IF. DISPLAY-FILE. DISPLAY "File content:" *> 循环遍历所有有效字符,逐个输出 PERFORM VARYING STRING-INDEX FROM 1 BY 1 UNTIL STRING-INDEX > ALLOCATED-LENGTH DISPLAY FILE-DATA-BASED (STRING-INDEX:1) WITH NO ADVANCING END-PERFORM. DISPLAY SPACE. *> 换行 CLEAN-UP. FREE FILE-DATA-POINTER.
关键修改说明
- 指针语法修正:拆分原
ALLOCATE语句的RETURNING与SET ADDRESS为两行,符合标准COBOL语法,避免歧义。 - 长度跟踪:新增
ALLOCATED-LENGTH变量,存储分配的总长度,同时在提前EOF时更新有效长度,防止越界访问。 - 存储访问逻辑:通过
FILE-DATA-BASED (STRING-INDEX:1)的引用修改方式,直接访问指针指向存储区域的对应位置,解决原单字符变量的长度限制问题。 - 显示逻辑调整:循环遍历所有有效字符并逐个输出,替代原直接显示单字符变量的方式,确保完整展示文件内容。
- 文件名处理:新增
INSPECT语句去除文件名尾部空格,避免因输入空格导致文件查找失败。
编译警告解决
原警告是因为FILE-DATA-HOLDER长度为1,引用修改的索引超出其定义范围。修改后,通过指针偏移访问分配的存储区域,符合标准COBOL引用修改规则,编译器不再触发警告。
内容的提问来源于stack exchange,提问作者drake14w
相关产品推荐
相关产品推荐

