プロが教えるわが家の防犯対策術!

汎用でCOBOL85で開発しています。

入力Fは固定長、
出力Fは可変長のCSV形式ファイルです。

質問なのは、
値と値の間にカンマを入れる(値がなくても必ず固定数入れる)にはどうすればいいか。
項目の末尾に半角空白が入っていた場合削除するにはどうすればよいか。
項目ごとにMOVE文を書くのではなく、LOOPさせるようにする(項目が多いので)

の書き方です。
半角空白は確か、項目の後ろから1バイトずつ数えて値があった時点で編集するというような
プログラムを見た記憶があるのですが、詳しい書き方がわかりません。
どなたか少しでもお分かりになりましたら教えてもらえないでしょうか。

A 回答 (5件)

コンパイル結果のリストで、コンパイラオプションの「STANDARD=(-A)」を確認してください。

「-A」が、「アドレス操作を抑止しない」という意味です。

入力ファイルの項目数が四個の場合で、例題を作ってみました。

【コーディング例】デバッグ用のDISPLAY文が入っています。
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN INFILE.
SELECT OUT-FILE ASSIGN OUTFILE.
DATA DIVISION.
FILE SECTION.
FD IN-FILE LABEL RECORD STANDARD.
01 IN-REC.
03 ITEM1 PIC X(10).
03 ITEM2 PIC X(1).
03 ITEM3 PIC X(5).
03 ITEM4 PIC X(15).
03 FILLER PIC X(41).
03 FILLER PIC X(8).
FD OUT-FILE LABEL RECORD STANDARD
RECORDING MODE V
RECORD VARYING
DEPENDING REC-LEN
BLOCK 10 RECORDS.
01 OUT-REC.
03 FILLER PIC X(500).
WORKING-STORAGE SECTION.
77 I PIC S9(4) COMP.
01 FILLER.
03 REC-LEN PIC S9(4) COMP.
03 DATA-LEN PIC S9(4) COMP.
03 DATA-POS PIC S9(4) COMP.
01 DATA-AREA ADDRESSED BY DATA-PTR.
03 FILLER PIC X
OCCURS 1 TO 500
DEPENDING DATA-LEN.
PROCEDURE DIVISION.
HAJIME.
OPEN INPUT IN-FILE.
OPEN OUTPUT OUT-FILE.
YOMIKOMI.
READ IN-FILE
AT END GO TO OWARI.
MOVE 500 TO REC-LEN.
MOVE 1 TO DATA-POS.
*
COMPUTE DATA-PTR = FUNCTION ADDR(ITEM1).
COMPUTE DATA-LEN = FUNCTION LENGTH(ITEM1).
PERFORM DATA-EXTRACT.
*
COMPUTE DATA-PTR = FUNCTION ADDR(ITEM2).
COMPUTE DATA-LEN = FUNCTION LENGTH(ITEM2).
PERFORM DATA-EXTRACT.
*
COMPUTE DATA-PTR = FUNCTION ADDR(ITEM3).
COMPUTE DATA-LEN = FUNCTION LENGTH(ITEM3).
PERFORM DATA-EXTRACT.
*
COMPUTE DATA-PTR = FUNCTION ADDR(ITEM4).
COMPUTE DATA-LEN = FUNCTION LENGTH(ITEM4).
PERFORM DATA-EXTRACT.
*
COMPUTE REC-LEN = DATA-POS - 2.
DISPLAY 'REC-LEN=' REC-LEN.
DISPLAY 'OUT-REC=(' OUT-REC(1:REC-LEN) ')'.
WRITE OUT-REC.
GO TO YOMIKOMI.
OWARI.
CLOSE IN-FILE OUT-FILE.
GOBACK.
DATA-EXTRACT.
DISPLAY 'EXTRACT STA'.
DISPLAY 'REC-LEN =' REC-LEN.
DISPLAY 'DATA-LEN=' DATA-LEN.
DISPLAY 'DATA-POS=' DATA-POS.
DISPLAY 'DATA-AREA=(' DATA-AREA ')'.
IF DATA-AREA NOT = ' '
PERFORM TEST BEFORE
VARYING I
FROM DATA-LEN BY -1
UNTIL (I < 1) OR (DATA-AREA(I:1) NOT = ' ')
CONTINUE
END-PERFORM
MOVE I TO DATA-LEN
STRING DATA-AREA ','
DELIMITED SIZE
INTO OUT-REC
WITH POINTER DATA-POS
END-STRING
ELSE
STRING ','
DELIMITED SIZE
INTO OUT-REC
WITH POINTER DATA-POS
END-STRING
END-IF.
DISPLAY 'EXTRACT END'.
DISPLAY 'REC-LEN =' REC-LEN.
DISPLAY 'DATA-LEN=' DATA-LEN.
DISPLAY 'DATA-POS=' DATA-POS.

この回答への補足

chukenkenkouさんへ
例題まで書いていただいてありがとうございました。
作成後コンパイルは電車で2時間かかるところで行うのですが(-o-;
少しでもエラーにならないように、
例題を参考にこれから解読してコーディングを始めようと思います。
本当にありがとうございました。
またわからない事があったらお聞きしてもいいでしょうか。
今回はありがとうございました。

補足日時:2006/11/27 10:47
    • good
    • 1

汎用のCOBOL85とは、日立でしょうか?



もしそうなら、「COMPUTE 変数 = FUNCTION ADDR(変数)」といった、アドレス操作機能は使用できるようになっていますか?

この回答への補足

chukenkenkouさん

そうです、日立です。
マニュアルを見たところ
COMPUTE (一意名1またはアドレス名1)= FUNCTION ADDR(一意名2)
といった書き方ができるとありました。

よろしくお願いしますm(__)m

補足日時:2006/11/24 15:25
    • good
    • 0

#2回答者です。


一箇所、訂正します。

【誤】
COMPUTE DATA-LEN = PTR1 - 1.

【正】
COMPUTE DATA-LEN = PTR1 - 2.

PTR1は、レコード中の最後のデータ転記時にも「,」をくっつけ、その後ろの位置を示しているので、有効なデータの最終位置は「-2」した値になります。
    • good
    • 0

「,」を追加するのは、STRING命令でいいと思います。

ループさせて処理させることも、私が使用していたCOBOLでは可能でした。
こんな感じでは、いかがでしょうか?
※後方の半角空白を除去するために探すのではなく、どこまで転記したかの位置情報から終端を知る方法にしています。

77 WK-CSV PIC X(1000).
77 PTR1 PIC S9(4) COMP.
77 I PIC S9(4) COMP.
77 DATA-LEN PIC S9(4) COMP.

INITIALIZE WK-CSV.
* 転記先の転記開始位置
MOVE 1 TO PTR1.

PERFORM TEST AFTER
VARYING I FROM 1 BY 1
UNTIL I NOT < n
STRING IN-DATA(I) ','
DELIMITED BY SPACE
INTO WK-CSV WITH POINTER PTR1
END-STRING
END-PERFORM.

COMPUTE DATA-LEN = PTR1 - 1.
MOVE WK-CSV(1:DATA-LEN) TO 出力領域.

この回答への補足

chukenkenkouさん、わかりやすいご説明ありがとうございます。

追加で質問させてください。
1.この場合「DELIMITED BY SPACE」と記入しても
データ途中の空白行はそのままで値を持ってこれるのでしょうか。
(データには「KYO TO」とか、「項目 名」のように、半角空白や全角空白が存在するようで)

2.入力ファイルはIN-DATA(I)でいいのでしょうか。
入力ファイルの定義の仕方がわからないのですが、
例えば入力項目が
01       A-REC.
 03      A-ABC.
  05     A-A      PIC X(001).
  05     A-B      PIC X(001).
  05     A-C      PIC X(001).
  05     A-DEF.          
   07    A-D      PIC X(005).
   07    A-E      PIC X(004).
   07    A-F      PIC X(005).
  05     A-YYYYMMDD.        
   07    A-YYYY     PIC X(004).
   07    A-MM      PIC X(002).
   07    A-DD      PIC X(002).
  05     A-CASE-A.        
   07    A-CASE     OCCURS 4 
               PIC X(002).
~続く

こういう感じでOCCURSやREDEFINESを含めかなり項目が多いのですが、
いったんワークにMOVEすればいいのでしょうか?
初歩的な質問ばかりですみません。
よろしくお願いします。

補足日時:2006/11/24 10:01
    • good
    • 1

STRING命令を使う ですかね


項目の途中にSPACEが無いのを条件として良いならば
INITIALIZE WK-OUTPUT-AREA
STRING A DELIMITED BY ' '
','
B DELIMITED BY ' '
','
.....
INTO WK-OUTPUT-AREA
~~
でCSV形式に編集
テーブルにしてるなら
MOVE A(1) TO WK-OUTPUT-AREA
PERFORM VARYING I FROM 2 BY 1 UNTIL I > xxx
STRING WK-OUTPUT-AREA DELIMITED BY ' '
',' DELIMITED BY SIZE
A(I) DELIMITED BY ' '
INTO WK-OUTPUT-A
END-STRING
 MOVE WK-OUTPUT-A TO WK-OUTPUT-AREA
END-PERFORM
みたいな感じでしょうか・・・
で、出力時のサイズが必要となるので
UNSTRING命令でSPACEまでの長さを分離・算出
FD OUTPUT-FILE
RECORDING MODE V
DEPENDING ON OUTPUT-LENGTH
の感じで定義しておいて
UNSTRING WK-OUTPUT-AREA
DELIMITED BY ' '
INTO OUTPUT-REC COUNT IN OUTPUT-LENGTH
END-UNSTRING
WRITE OUTPUT-REC

DEBUGしてないのでちょっと自信無しです。

この回答への補足

回答ありがとうございます。
ただ「データ途中の半角空白等は削除しない」とあるので項目途中にも空白がくる事が考えられます。すみません。
STRINGだと項目途中でも変換されてしまうのでしょうか?

入力FはCOPY句があるのですが出力Fは何もなく、
ただ「CSV形式ファイル(可変長)」とあるだけです。
出力Fはテーブル定義したほうがいいのでしょうか。

上司には以下のようにやらない方が(LOOPでまわす方がきれい)いいと言われたので、
* 出力ファイル編集エリア
01 WK-CSV.
   03 WK-NAME     PIC N(10).
   03 FILLER      PIC X(01)   VALUE ",".
   03 WK-NAME-YOMI   PIC X(10).
   03 FILLER      PIC X(01)   VALUE ",".
   03 WK-CLUB     PIC N(10).
   03 FILLER      PIC X(01)   VALUE ",".
(これでは空白削除もできないですね、そういえば)

01 WK-CSV PIC X(10000).
みたいにして、[データ,データ,…]とデータが入っていればいいかなと思ったのです。
何か解決策がありましたらお願いしますm(__)m

補足日時:2006/11/22 10:01
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています