cv.cm

編碼 · 程式語言

COBOL 入門教學

閱讀約 9 分鐘

簡答

COBOL(Common Business-Oriented Language)是為商業資料處理而設計的編譯式語言,擅長處理記錄、檔案、報表與精確的十進位運算。程式分成四個 Division,資料以 PIC(picture)子句描述,程式碼讀起來像 ADD AMOUNT TO TOTAL 這樣的英文句子。它至今仍在銀行、保險公司與政府機關運行核心系統,大多在 IBM 大型主機上。你可以用免費的 GnuCOBOL 編譯器學習:cobc -x hello.cob。

COBOL 是什麼、誰在使用

COBOL 由 CODASYL 委員會於 1959 年設計,深受 Grace Hopper 早期 FLOW-MATIC 語言的影響。它由 ISO 標準化;後來的標準加入了結構化程式設計、物件導向及其他特性,最新的修訂版於 2023 年發布。

COBOL 用於批次處理與交易系統:帳戶處理、薪資、保險理賠、稅務與福利系統。這類程式碼大多運行在 IBM Z 大型主機上,使用 IBM Enterprise COBOL,搭配處理交易的 CICS 與資料庫 Db2。維護並現代化這些系統的工作機會仍然很常見。

安裝 GnuCOBOL 並執行 Hello, world

GnuCOBOL 是免費的編譯器,會把 COBOL 轉譯成 C,再編譯成原生程式。許多 Linux 發行版都有 gnucobol 套件,macOS 可透過 Homebrew 安裝;Windows 使用者可以用 WSL 或預先建置的套件。

       IDENTIFICATION DIVISION.
       PROGRAM-ID. HELLO.
       PROCEDURE DIVISION.
           DISPLAY "Hello, world!".
           STOP RUN.
cobc -x hello.cob
./hello
# Hello, world!

這段程式碼採用傳統的固定格式:第 1 到 6 欄用於序號,第 7 欄標示註解(*)或接續行,A 區(第 8 到 11 欄)放置 Division、Section 與段落名稱,B 區(第 12 到 72 欄)放置陳述式。GnuCOBOL 也接受自由格式的原始碼,用法是 cobc -x -free。選項 -x 會建置可執行檔,而不是模組。

四大 Division

Division用途
IDENTIFICATION DIVISION為程式命名(PROGRAM-ID)
ENVIRONMENT DIVISION將程式連接到外部環境,例如它使用哪些檔案
DATA DIVISION宣告所有資料:檔案記錄、工作儲存區、參數
PROCEDURE DIVISION可執行的陳述式,組織成段落

每個變數在使用前,都必須在 DATA DIVISION 中宣告。WORKING-STORAGE SECTION 存放程式的變數,FILE SECTION 描述檔案記錄,LINKAGE SECTION 則描述呼叫者傳入的參數。

資料與 PIC 子句

COBOL 以精確的版面配置來描述資料。層級編號表示階層(01 是一筆記錄,05 是其中的欄位),PIC 子句則給出格式:X 是任意字元,9 是數字,S 是正負號,V 是隱含的小數點。

宣告意義範例值
PIC X(10)10 個字元,以空格補齊"Ana "
PIC 9(3)無號的 3 位數字030
PIC S9(5)V99有號,小數點前 5 位、後 2 位-01234.50
PIC $ZZ,ZZ9.99編輯後的輸出:貨幣符號,前置的零以空格顯示$ 1,234.50
PIC S9(7)V99 COMP-3緊縮十進位(packed decimal),在大型主機上很常見儲存為 5 個位元組
88 IS-DONE VALUE "Y"條件名稱:對其父欄位做的布林測試IF IS-DONE
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DATA-DEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-NAME        PIC X(10)      VALUE "Ana".
       01  WS-AGE         PIC 9(3)       VALUE 30.
       01  WS-PRICE       PIC S9(5)V99   VALUE 1234.50.
       01  WS-PRICE-OUT   PIC $ZZ,ZZ9.99.
       01  WS-CUSTOMER.
           05  WS-FIRST   PIC X(10).
           05  WS-LAST    PIC X(15).
       PROCEDURE DIVISION.
           MOVE WS-PRICE TO WS-PRICE-OUT
           DISPLAY WS-NAME "is " WS-AGE
           DISPLAY "Price: " WS-PRICE-OUT
           STOP RUN.
      *> Ana       is 030
      *> Price: $ 1,234.50

數字以十進位儲存,所以 0.10 + 0.20 恰好是 0.30,這是 COBOL 適合處理金額的原因之一。WS-CUSTOMER 是群組項目:可以整個一起搬移,也可以逐欄搬移。

流程控制:IF、EVALUATE 與 PERFORM

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CONTROL-DEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-I        PIC 99.
       01  WS-TOTAL    PIC 9(4) VALUE 0.
       01  WS-SCORE    PIC 999  VALUE 85.
       PROCEDURE DIVISION.
           PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10
               ADD WS-I TO WS-TOTAL
           END-PERFORM
           DISPLAY "Total: " WS-TOTAL
           EVALUATE TRUE
               WHEN WS-SCORE >= 90
                   DISPLAY "A"
               WHEN WS-SCORE >= 80
                   DISPLAY "B"
               WHEN OTHER
                   DISPLAY "C"
           END-EVALUATE
           IF WS-TOTAL > 50
               DISPLAY "big"
           ELSE
               DISPLAY "small"
           END-IF
           STOP RUN.
      *> Total: 0055
      *> B
      *> big

PERFORM VARYING 是 COBOL 的計數迴圈,PERFORM UNTIL condition 則是它的 while 迴圈。EVALUATE 是 switch 陳述式。END-IF 與 END-PERFORM 等範圍終止符會結束各個區塊;句點則結束整個句子。

段落、算術與表格

COBOL 沒有一般意義上的函式。你把邏輯組織成具名段落,再用 PERFORM 執行;較大的單元則成為獨立程式,用 CALL "PROG" USING ... 呼叫。算術使用動詞(ADD、SUBTRACT、MULTIPLY、DIVIDE),或用 COMPUTE 搭配公式。陣列稱為表格,以 OCCURS 宣告,索引從 1 開始。

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PARA-DEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-PRICES.
           05  WS-PRICE   PIC 9(3)V99 OCCURS 3 TIMES.
       01  WS-I           PIC 9.
       01  WS-SUM         PIC 9(4)V99 VALUE 0.
       01  WS-SUM-OUT     PIC Z,ZZ9.99.
       PROCEDURE DIVISION.
       MAIN-PARA.
           MOVE 10.50 TO WS-PRICE(1)
           MOVE 4.25  TO WS-PRICE(2)
           MOVE 7.00  TO WS-PRICE(3)
           PERFORM ADD-PRICE VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 3
           COMPUTE WS-SUM = WS-SUM * 1.1
           MOVE WS-SUM TO WS-SUM-OUT
           DISPLAY "With 10% tax: " WS-SUM-OUT
           STOP RUN.
       ADD-PRICE.
           ADD WS-PRICE(WS-I) TO WS-SUM.
      *> With 10% tax:    23.92

總和是 21.75;乘以 1.1 為 23.925,COBOL 會截斷到宣告的兩位小數(23.92),除非你寫 COMPUTE ... ROUNDED。

錯誤處理

日常的 COBOL 程式碼沒有例外。取而代之的是,陳述式帶有條件子句:ON SIZE ERROR 處理算術溢位或除以零,AT END 處理檔案結尾,INVALID KEY 處理索引檔,另有 FILE STATUS 欄位,會在每次檔案操作後接收兩個字元的代碼("00" 代表成功)。

           DIVIDE WS-A BY WS-B GIVING WS-C
               ON SIZE ERROR
                   DISPLAY "Division failed"
               NOT ON SIZE ERROR
                   DISPLAY "Result: " WS-C
           END-DIVIDE

完整的小程式:銷售檔案總計

從檔案讀取固定格式的記錄,是典型的 COBOL 工作。這個程式讀取 sales.txt,其中每一行有 10 個字元的品名,後面接著 7 位數的金額(含兩位隱含小數)。

apples    0001250
pears     0000899
plums     0002000
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SALES-TOTAL.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT SALES-FILE ASSIGN TO "sales.txt"
               ORGANIZATION IS LINE SEQUENTIAL
               FILE STATUS IS WS-FS.
       DATA DIVISION.
       FILE SECTION.
       FD  SALES-FILE.
       01  SALES-REC.
           05  SR-ITEM     PIC X(10).
           05  SR-AMOUNT   PIC 9(5)V99.
       WORKING-STORAGE SECTION.
       01  WS-FS           PIC XX.
       01  WS-EOF          PIC X VALUE "N".
           88  NO-MORE-RECORDS       VALUE "Y".
       01  WS-TOTAL        PIC 9(7)V99 VALUE 0.
       01  WS-TOTAL-OUT    PIC Z,ZZZ,ZZ9.99.
       PROCEDURE DIVISION.
           OPEN INPUT SALES-FILE
           IF WS-FS NOT = "00"
               DISPLAY "Cannot open file, status " WS-FS
               STOP RUN
           END-IF
           PERFORM UNTIL NO-MORE-RECORDS
               READ SALES-FILE
                   AT END SET NO-MORE-RECORDS TO TRUE
                   NOT AT END ADD SR-AMOUNT TO WS-TOTAL
               END-READ
           END-PERFORM
           CLOSE SALES-FILE
           MOVE WS-TOTAL TO WS-TOTAL-OUT
           DISPLAY "Total sales: " WS-TOTAL-OUT
           STOP RUN.

執行後會印出 Total sales:,後面接著靠右對齊在 12 個字元編輯欄位中的 41.49。LINE SEQUENTIAL 代表每行一筆記錄的文字檔;GnuCOBOL 與其他 PC 編譯器支援它,而大型主機程式通常讀取 JCL 中定義的固定長度資料集。

接下來可以學什麼

  • GnuCOBOL 專案頁面及其 Programmer's Guide,提供完整的語言參考。
  • IBM 的 Enterprise COBOL for z/OS 文件,涵蓋大型主機 COBOL、CICS 與 Db2 的用法。
  • 練習讀寫檔案、使用 SORT 動詞排序,以及產生格式化報表。
  • 如果想處理正式系統,請學習周邊的大型主機工具(JCL、TSO/ISPF)。

常見問題

COBOL 現在還有人用嗎?

有。許多銀行、保險公司與政府機關仍用 COBOL 程式執行核心的批次與交易處理,因此對能維護並現代化這些系統的開發者仍有持續的需求。

COBOL 很難學嗎?

它的語法冗長但簡單,大多數初學者都能很快寫出可運作的程式。比較難的是它周邊的大型主機環境:JCL、資料集、CICS 與 Db2。

沒有大型主機也能學 COBOL 嗎?

可以。GnuCOBOL 能在 Linux、macOS 與 Windows 上執行,並支援標準 COBOL,所以你可以先在一般電腦上學這門語言,再轉到大型主機。

為什麼 COBOL 使用十進位數字?

金額等商業資料必須精確。COBOL 以固定小數位數的十進位數字儲存數值,避免了二進位浮點數的捨入誤差。

全部編碼教學