You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

标准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.

关键修改说明

  1. 指针语法修正:拆分原ALLOCATE语句的RETURNING与SET ADDRESS为两行,符合标准COBOL语法,避免歧义。
  2. 长度跟踪:新增ALLOCATED-LENGTH变量,存储分配的总长度,同时在提前EOF时更新有效长度,防止越界访问。
  3. 存储访问逻辑:通过FILE-DATA-BASED (STRING-INDEX:1)的引用修改方式,直接访问指针指向存储区域的对应位置,解决原单字符变量的长度限制问题。
  4. 显示逻辑调整:循环遍历所有有效字符并逐个输出,替代原直接显示单字符变量的方式,确保完整展示文件内容。
  5. 文件名处理:新增INSPECT语句去除文件名尾部空格,避免因输入空格导致文件查找失败。

编译警告解决

原警告是因为FILE-DATA-HOLDER长度为1,引用修改的索引超出其定义范围。修改后,通过指针偏移访问分配的存储区域,符合标准COBOL引用修改规则,编译器不再触发警告。

内容的提问来源于stack exchange,提问作者drake14w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:44:51