• ベストアンサー

COBOL、項目末尾に空白がある場合削除の方法その他

汎用でCOBOL85で開発しています。 入力Fは固定長、 出力Fは可変長のCSV形式ファイルです。 質問なのは、 値と値の間にカンマを入れる(値がなくても必ず固定数入れる)にはどうすればいいか。 項目の末尾に半角空白が入っていた場合削除するにはどうすればよいか。 項目ごとにMOVE文を書くのではなく、LOOPさせるようにする(項目が多いので) の書き方です。 半角空白は確か、項目の後ろから1バイトずつ数えて値があった時点で編集するというような プログラムを見た記憶があるのですが、詳しい書き方がわかりません。 どなたか少しでもお分かりになりましたら教えてもらえないでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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.

MissWednesday
質問者

補足

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

その他の回答 (4)

回答No.4

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

MissWednesday
質問者

補足

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

回答No.3

#2回答者です。 一箇所、訂正します。 【誤】 COMPUTE DATA-LEN = PTR1 - 1. 【正】 COMPUTE DATA-LEN = PTR1 - 2. PTR1は、レコード中の最後のデータ転記時にも「,」をくっつけ、その後ろの位置を示しているので、有効なデータの最終位置は「-2」した値になります。

回答No.2

「,」を追加するのは、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 出力領域.

MissWednesday
質問者

補足

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すればいいのでしょうか? 初歩的な質問ばかりですみません。 よろしくお願いします。

  • S-Wat
  • ベストアンサー率23% (72/302)
回答No.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してないのでちょっと自信無しです。

MissWednesday
質問者

補足

回答ありがとうございます。 ただ「データ途中の半角空白等は削除しない」とあるので項目途中にも空白がくる事が考えられます。すみません。 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

関連するQ&A