今回は、商品名、金額を含む入力ファイル(sales.csv)を読み取り、商品ごとの売上金額を合計し、summary.csv に出力するプログラムをご紹介しよう。
入力ファイル:sales.csv
りんご,100
みかん,150
りんご,120
出力ファイル:summary.csv
りんご ,000220
みかん ,000150
プログラム:sales_summary.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. SALES-SUMMARY.
*> 入力ファイル:sales.csv(商品名,金額)
*> 商品ごとの売上金額を合計し、summary.csv に出力
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INPUT-FILE ASSIGN TO "sales.csv"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT OUTPUT-FILE ASSIGN TO "summary.csv"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD INPUT-FILE.
01 INPUT-RECORD PIC X(80).
FD OUTPUT-FILE.
01 OUTPUT-RECORD PIC X(80).
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
01 WS-LINE PIC X(80).
01 WS-NAME PIC X(20).
01 WS-AMOUNT-STR PIC X(10).
01 WS-AMOUNT PIC 9(6) COMP-5.
01 WS-NAME1 PIC X(20) VALUE SPACES.
01 WS-TOTAL1 PIC 9(6) VALUE 0.
01 WS-NAME2 PIC X(20) VALUE SPACES.
01 WS-TOTAL2 PIC 9(6) VALUE 0.
PROCEDURE DIVISION.
MAIN.
OPEN INPUT INPUT-FILE
OPEN OUTPUT OUTPUT-FILE
PERFORM UNTIL WS-EOF = "Y"
READ INPUT-FILE
AT END
MOVE "Y" TO WS-EOF
NOT AT END
MOVE INPUT-RECORD TO WS-LINE
PERFORM PARSE-LINE
PERFORM UPDATE-TOTALS
END-READ
END-PERFORM
PERFORM WRITE-TOTALS
CLOSE INPUT-FILE
CLOSE OUTPUT-FILE
STOP RUN.
PARSE-LINE.
UNSTRING WS-LINE
DELIMITED BY ","
INTO WS-NAME, WS-AMOUNT-STR
MOVE FUNCTION NUMVAL (WS-AMOUNT-STR) TO WS-AMOUNT.
UPDATE-TOTALS.
IF WS-NAME = WS-NAME1
ADD WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME1 = SPACES
MOVE WS-NAME TO WS-NAME1
MOVE WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME = WS-NAME2
ADD WS-AMOUNT TO WS-TOTAL2
ELSE IF WS-NAME2 = SPACES
MOVE WS-NAME TO WS-NAME2
MOVE WS-AMOUNT TO WS-TOTAL2
END-IF.
WRITE-TOTALS.
IF WS-NAME1 NOT = SPACES
STRING WS-NAME1 DELIMITED BY SIZE
"," DELIMITED BY SIZE
WS-TOTAL1 DELIMITED BY SIZE
INTO OUTPUT-RECORD
WRITE OUTPUT-RECORD
END-IF
IF WS-NAME2 NOT = SPACES
STRING WS-NAME2 DELIMITED BY SIZE
"," DELIMITED BY SIZE
WS-TOTAL2 DELIMITED BY SIZE
INTO OUTPUT-RECORD
WRITE OUTPUT-RECORD
END-IF.
コンパイルと実行
cobc -x -free sales_summary.cob
./sales_summary
COBOLの -free オプションを使う場合、コメントは *> を使うこと。
*> 入力ファイル:sales.csv(商品名,金額)
*> 商品ごとの売上金額を合計し、summary.csv に出力
* だけのコメントは、固定形式ではOKだが、自由形式ではエラーになる。
1. IDENTIFICATION DIVISION
IDENTIFICATION DIVISION.
PROGRAM-ID. SALES-SUMMARY
- プログラムの識別情報を記述するセクションである。
- PROGRAM-ID はプログラム名。今回は、SALES-SUMMARYである。
2. ENVIRONMENT DIVISION
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT INPUT-FILE ASSIGN TO "sales.csv"
ORGANIZATION IS LINE SEQUENTIAL.
SELECT OUTPUT-FILE ASSIGN TO "summary.csv"
ORGANIZATION IS LINE SEQUENTIAL.
- ファイルの入出力に関する設定をする。
- sales.csv を読み込み用ファイル、summary.csv を書き込み用ファイルとして指定する。
- LINE SEQUENTIAL はテキストファイルを1行ずつ処理する形式である。
3. DATA DIVISION
FILE SECTION
FD INPUT-FILE.
01 INPUT-RECORD PIC X(80).
FD OUTPUT-FILE.
01 OUTPUT-RECORD PIC X(80).
- ファイルのレコード構造を定義する。
- 各行最大80文字まで読み書き可能である。
WORKING-STORAGE SECTION
01 WS-EOF PIC X VALUE "N".
01 WS-LINE PIC X(80).
01 WS-NAME PIC X(20).
01 WS-AMOUNT-STR PIC X(10).
01 WS-AMOUNT PIC 9(6) COMP-5.
01 WS-NAME1 PIC X(20) VALUE SPACES.
01 WS-TOTAL1 PIC 9(6) VALUE 0.
01 WS-NAME2 PIC X(20) VALUE SPACES.
01 WS-TOTAL2 PIC 9(6) VALUE 0.
- 作業領域の変数定義をする。
- WS-EOF はファイルの終端判定する。
- WS-NAME, WS-AMOUNT-STR はCSVの分解結果である。
- WS-AMOUNT は数値変換後の金額である。
- WS-NAME1, WS-NAME2 は商品名(最大2種類)である。
- 作業領域の変数定義をする。
- WS-EOF はファイルの終端判定をする。
- WS-NAME, WS-AMOUNT-STR はCSVの分解結果である。
- WS-AMOUNT は数値変換後の金額である。
- WS-NAME1, WS-NAME2 は商品名(最大2種類)である。
- WS-TOTAL1, WS-TOTAL2 はそれぞれの合計金額である
4. PROCEDURE DIVISION
MAIN処理
OPEN INPUT INPUT-FILE
OPEN OUTPUT OUTPUT-FILE
PERFORM UNTIL WS-EOF = "Y"
READ INPUT-FILE
AT END
MOVE "Y" TO WS-EOF
NOT AT END
MOVE INPUT-RECORD TO WS-LINE
PERFORM PARSE-LINE
PERFORM UPDATE-TOTALS
END-READ
END-PERFORM
PERFORM WRITE-TOTALS
CLOSE INPUT-FILE
CLOSE OUTPUT-FILE
STOP RUN.
- ファイルを開いて、1行ずつ読み込む。
- PARSE-LINE でCSVを分解する。
- UPDATE-TOTALS で商品ごとの合計を更新する。
- 最後に WRITE-TOTALS で結果を書き出す。
PARSE-LINE(CSV分解)
UNSTRING WS-LINE
DELIMITED BY ","
INTO WS-NAME, WS-AMOUNT-STR
MOVE FUNCTION NUMVAL (WS-AMOUNT-STR) TO WS-AMOUNT.
- UNSTRING で商品名と金額を分離する。
- NUMVAL 関数で文字列から数値に変換する。
UPDATE-TOTALS(集計処理)
IF WS-NAME = WS-NAME1
ADD WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME1 = SPACES
MOVE WS-NAME TO WS-NAME1
MOVE WS-AMOUNT TO WS-TOTAL1
ELSE IF WS-NAME = WS-NAME2
ADD WS-AMOUNT TO WS-TOTAL2
ELSE IF WS-NAME2 = SPACES
MOVE WS-NAME TO WS-NAME2
MOVE WS-AMOUNT TO WS-TOTAL2
END-IF.
- 商品名が既存のものと一致すれば加算する。
- 初めての名前なら登録して初期化する。
- 商品は最大2種類まで対応する。
WRITE-TOTALS(出力処理)
IF WS-NAME1 NOT = SPACES
STRING WS-NAME1 DELIMITED BY SIZE
"," DELIMITED BY SIZE
WS-TOTAL1 DELIMITED BY SIZE
INTO OUTPUT-RECORD
WRITE OUTPUT-RECORD
END-IF
IF WS-NAME2 NOT = SPACES
STRING WS-NAME2 DELIMITED BY SIZE
"," DELIMITED BY SIZE
WS-TOTAL2 DELIMITED BY SIZE
INTO OUTPUT-RECORD
WRITE OUTPUT-RECORD
END-IF.
- 商品名と合計金額をCSV形式で出力する。
- STRING で1行を構築し、WRITE で書き込みする。
コメント