COBOLの文字列操作は、他の言語のように演算子(+や&)で連結するのではなく、STRING文・UNSTRING文・INSPECT文といった専用の命令を使います。最初は独特に感じますが、仕組みを理解するとバッチ処理や帳票出力で非常に強力に使えます。
この記事では、文字列の結合に使うSTRING文を基礎から解説し、分割のUNSTRING文、文字変換のINSPECT文、さらに現代COBOLの文字列関数まで体系的に説明します。CSV組み立てや日付整形などの実践コードも合わせて紹介します。
- STRING文の構文と DELIMITED BY SIZE / DELIMITED BY 文字の違い
- WITH POINTER で結合位置を制御する方法
- ON OVERFLOW で桁あふれを検知する方法
- UNSTRING文で文字列を分割する方法
- INSPECT文で文字の置換・変換を行う方法
- FUNCTION CONCATENATE / TRIM など現代COBOLの文字列関数
- CSV組み立て・日付整形・ログ出力の実践パターン
STRING文の基本構文
STRING文は複数の文字列を順番に結合して、1つの変数(受け取り領域)に書き込む命令です。
STRING 送り元1 [送り元2 ...] DELIMITED BY {SIZE | 区切り文字}
[送り元3 [送り元4 ...] DELIMITED BY {SIZE | 区切り文字}]
...
INTO 受け取り先
[WITH POINTER ポインタ変数]
[ON OVERFLOW 処理]
[NOT ON OVERFLOW 処理]
END-STRING.
| 句 | 説明 |
|---|---|
| DELIMITED BY SIZE | 送り元のPIC句で定義した全桁をそのまま転送する(スペースも含む) |
| DELIMITED BY 文字 | 指定した文字(スペース等)が現れた位置で転送を打ち切る |
| INTO 受け取り先 | 結合結果を書き込む変数。事前にSPACESで初期化しておくのが定石 |
| WITH POINTER | 書き込み開始位置(1始まり)を変数で管理する。複数回のSTRINGで同一領域に追記できる |
| ON OVERFLOW | 受け取り先の容量を超えた場合に実行する処理 |
DELIMITED BY SIZEとDELIMITED BY SPACEの違い
この2つの違いはCOBOL文字列操作で最初に理解すべき重要なポイントです。
WORKING-STORAGE SECTION.
01 WS-FIRST PIC X(10) VALUE 'TARO '. *> 後ろにスペース6文字
01 WS-LAST PIC X(10) VALUE 'YAMADA '. *> 後ろにスペース4文字
01 WS-RESULT-A PIC X(25) VALUE SPACES.
01 WS-RESULT-B PIC X(25) VALUE SPACES.
PROCEDURE DIVISION.
*--- DELIMITED BY SIZE: 全桁転送(スペースも含む)---
STRING WS-FIRST DELIMITED BY SIZE
' ' DELIMITED BY SIZE *> 区切り文字として半角スペース1文字
WS-LAST DELIMITED BY SIZE
INTO WS-RESULT-A
*> 結果: 'TARO YAMADA '(スペース込みで20文字+区切り1文字)
*--- DELIMITED BY SPACE: 最初のスペースまでを転送 ---
MOVE SPACES TO WS-RESULT-B
STRING WS-FIRST DELIMITED BY SPACE *> 'TARO'の4文字のみ(スペース手前まで)
' ' DELIMITED BY SIZE *> 区切りスペース
WS-LAST DELIMITED BY SPACE *> 'YAMADA'の6文字のみ
INTO WS-RESULT-B
*> 結果: 'TARO YAMADA '(有効文字のみ)
DISPLAY 'SIZE: [' WS-RESULT-A ']'
DISPLAY 'SPACE: [' WS-RESULT-B ']'
STOP RUN.
- DELIMITED BY SIZE: 数値編集項目・固定長コード(01, JP等)を結合するとき
- DELIMITED BY SPACE: 可変長の文字データ(名前・住所等)を詰めて結合するとき
- DELIMITED BY 文字: カンマやスラッシュなど特定の区切り文字まで転送するとき
WITH POINTERで書き込み位置を制御する
WITH POINTER句を使うと、書き込みの開始位置を指定できます。ループで繰り返しSTRINGを呼び出すときや、1つの大きな出力領域に複数回追記するときに使います。
WORKING-STORAGE SECTION.
01 WS-BUFFER PIC X(80) VALUE SPACES.
01 WS-PTR PIC 9(3) VALUE 1. *> 書き込み開始位置(1から始まる)
01 WS-ITEM PIC X(20).
PROCEDURE DIVISION.
MOVE 1 TO WS-PTR
*> 1回目: バッファ先頭から書き込み
MOVE '2024-01-15' TO WS-ITEM
STRING WS-ITEM DELIMITED BY SPACE
INTO WS-BUFFER
WITH POINTER WS-PTR
*> WS-PTR = 11(10文字書き込んだので次の開始位置が11)
*> 2回目: カンマ区切りを追加
STRING ',' DELIMITED BY SIZE
INTO WS-BUFFER
WITH POINTER WS-PTR
*> WS-PTR = 12
*> 3回目: 次のデータを追記
MOVE 'TANAKA JIRO' TO WS-ITEM
STRING WS-ITEM DELIMITED BY SPACE
INTO WS-BUFFER
WITH POINTER WS-PTR
DISPLAY WS-BUFFER. *> '2024-01-15,TANAKA JIRO'
STOP RUN.
ON OVERFLOW / NOT ON OVERFLOW
書き込み先の容量を超えた場合(ポインタが最大桁を越えた場合)、ON OVERFLOWが実行されます。
WORKING-STORAGE SECTION.
01 WS-OUT PIC X(10) VALUE SPACES.
01 WS-A PIC X(8) VALUE 'ABCDEFGH'.
01 WS-B PIC X(8) VALUE 'IJKLMNOP'.
01 WS-OVERFLOW-FLG PIC X(1) VALUE 'N'.
PROCEDURE DIVISION.
STRING WS-A DELIMITED BY SIZE
WS-B DELIMITED BY SIZE
INTO WS-OUT
ON OVERFLOW
MOVE 'Y' TO WS-OVERFLOW-FLG
DISPLAY '警告: 文字列が受け取り領域を超えました'
NOT ON OVERFLOW
DISPLAY '正常に結合しました'
END-STRING
IF WS-OVERFLOW-FLG = 'Y'
*> WS-OUTは最初の10文字まで書き込まれている
DISPLAY '実際の結果: [' WS-OUT ']' *> 'ABCDEFGHIJ'(途中まで)
END-IF.
ON OVERFLOWが発生しても、書き込み先に収まる部分まではデータが書き込まれます。OVERFLOWは「書き込めなかった部分が発生した」という通知であり、全体を中断するわけではありません。受け取り先の桁数はあらかじめ十分に確保しておきましょう。
UNSTRING文で文字列を分割する
UNSTRING文はSTRINGの逆で、1つの文字列を指定した区切り文字で分割して複数の変数に振り分けます。CSVのパースや固定フォーマットからのフィールド抽出に使います。
UNSTRING 送り元
DELIMITED BY [ALL] 区切り文字 [OR [ALL] 区切り文字2 ...]
INTO 受け取り1 [DELIMITER IN 区切り保存先1] [COUNT IN 文字数1]
受け取り2 [DELIMITER IN 区切り保存先2] [COUNT IN 文字数2]
...
[WITH POINTER ポインタ変数]
[TALLYING IN カウンタ変数]
[ON OVERFLOW 処理]
[NOT ON OVERFLOW 処理]
END-UNSTRING.
WORKING-STORAGE SECTION.
01 WS-CSV-LINE PIC X(60) VALUE '20240115,TANAKA JIRO,TOKYO,35'.
01 WS-DATE PIC X(8).
01 WS-NAME PIC X(20).
01 WS-CITY PIC X(20).
01 WS-AGE PIC X(3).
01 WS-FIELD-COUNT PIC 9(2).
PROCEDURE DIVISION.
MOVE SPACES TO WS-DATE WS-NAME WS-CITY WS-AGE
MOVE 0 TO WS-FIELD-COUNT
UNSTRING WS-CSV-LINE
DELIMITED BY ','
INTO WS-DATE
WS-NAME
WS-CITY
WS-AGE
TALLYING IN WS-FIELD-COUNT
END-UNSTRING
DISPLAY '日付: ' WS-DATE *> '20240115'
DISPLAY '氏名: ' WS-NAME *> 'TANAKA JIRO'
DISPLAY '都市: ' WS-CITY *> 'TOKYO'
DISPLAY '年齢: ' WS-AGE *> '35'
DISPLAY 'フィールド数: ' WS-FIELD-COUNT *> 4
STOP RUN.
WORKING-STORAGE SECTION.
01 WS-INPUT PIC X(30) VALUE 'TOKYO/OSAKA NAGOYA,FUKUOKA'.
01 WS-CITY1 PIC X(10).
01 WS-CITY2 PIC X(10).
01 WS-CITY3 PIC X(10).
01 WS-CITY4 PIC X(10).
PROCEDURE DIVISION.
UNSTRING WS-INPUT
DELIMITED BY '/' OR SPACE OR ',' *> 3種類の区切りに対応
INTO WS-CITY1 WS-CITY2 WS-CITY3 WS-CITY4
END-UNSTRING
DISPLAY WS-CITY1 *> 'TOKYO'
DISPLAY WS-CITY2 *> 'OSAKA'
DISPLAY WS-CITY3 *> 'NAGOYA'
DISPLAY WS-CITY4 *> 'FUKUOKA'
WORKING-STORAGE SECTION.
01 WS-DATA PIC X(30) VALUE 'APPLE,BANANA/CHERRY'.
01 WS-ITEM1 PIC X(10).
01 WS-ITEM2 PIC X(10).
01 WS-ITEM3 PIC X(10).
01 WS-DELIM1 PIC X(1). *> ITEM1の後の区切り文字
01 WS-DELIM2 PIC X(1). *> ITEM2の後の区切り文字
PROCEDURE DIVISION.
UNSTRING WS-DATA
DELIMITED BY ',' OR '/'
INTO WS-ITEM1 DELIMITER IN WS-DELIM1
WS-ITEM2 DELIMITER IN WS-DELIM2
WS-ITEM3
END-UNSTRING
DISPLAY WS-ITEM1 WS-DELIM1 *> 'APPLE ,'
DISPLAY WS-ITEM2 WS-DELIM2 *> 'BANANA /'
DISPLAY WS-ITEM3 *> 'CHERRY'
INSPECT文で文字を置換・変換する
INSPECT文は文字列内を走査して文字をカウントしたり、特定の文字を別の文字に置き換えたりします。大文字・小文字変換や文字のサニタイズによく使われます。
| 書き方 | 用途 |
|---|---|
| INSPECT … TALLYING | 指定した文字の出現回数をカウントする |
| INSPECT … REPLACING | 指定した文字を別の文字に置き換える |
| INSPECT … CONVERTING | 文字の対応表で一括変換する(大小変換に便利) |
| INSPECT … TALLYING REPLACING | カウントと置き換えを同時に行う |
WORKING-STORAGE SECTION.
01 WS-TEXT PIC X(30) VALUE 'Hello World COBOL 2024'.
01 WS-LOWER-A PIC X(26) VALUE 'abcdefghijklmnopqrstuvwxyz'.
01 WS-UPPER-A PIC X(26) VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
PROCEDURE DIVISION.
*> 小文字 → 大文字
INSPECT WS-TEXT
CONVERTING WS-LOWER-A TO WS-UPPER-A
DISPLAY WS-TEXT *> 'HELLO WORLD COBOL 2024'
*> 大文字 → 小文字(逆向き)
MOVE 'Hello World' TO WS-TEXT
INSPECT WS-TEXT
CONVERTING WS-UPPER-A TO WS-LOWER-A
DISPLAY WS-TEXT *> 'hello world'
WORKING-STORAGE SECTION.
01 WS-PATH PIC X(40) VALUE 'C:\COBOL\SOURCE\PROGRAM.CBL'.
01 WS-COUNT PIC 9(3) VALUE 0.
PROCEDURE DIVISION.
*> バックスラッシュをスラッシュに置換(UNIX形式に変換)
INSPECT WS-PATH
REPLACING ALL '' BY '/'
DISPLAY WS-PATH *> 'C:/COBOL/SOURCE/PROGRAM.CBL'
*> スペースをアンダースコアに置換
MOVE 'TOKYO OSAKA NAGOYA' TO WS-PATH
INSPECT WS-PATH
REPLACING ALL SPACE BY '_'
DISPLAY WS-PATH *> 'TOKYO_OSAKA_NAGOYA'
WORKING-STORAGE SECTION.
01 WS-CSV PIC X(50) VALUE 'A001,B002,C003,D004,E005'.
01 WS-COMMA-CNT PIC 9(3) VALUE 0.
PROCEDURE DIVISION.
INSPECT WS-CSV
TALLYING WS-COMMA-CNT FOR ALL ','
DISPLAY 'カンマの数: ' WS-COMMA-CNT *> '4'
*> フィールド数 = WS-COMMA-CNT + 1 = 5
現代COBOLの文字列関数(COBOL 2002以降)
COBOL 2002規格からINTRINSIC FUNCTION(組み込み関数)が整備され、文字列操作が大幅に簡潔に書けるようになりました。IBM Enterprise COBOLやGnuCOBOLでも使用できます。
| 関数 | 機能 |
|---|---|
| FUNCTION CONCATENATE(str1 str2…) | 複数の文字列を連結して返す |
| FUNCTION TRIM(str [LEADING|TRAILING]) | 先頭・末尾のスペースを除去する |
| FUNCTION UPPER-CASE(str) | 文字列を大文字に変換する |
| FUNCTION LOWER-CASE(str) | 文字列を小文字に変換する |
| FUNCTION LENGTH(str) | 文字列の長さ(バイト数)を返す |
| FUNCTION REVERSE(str) | 文字列を逆順にして返す |
| FUNCTION SUBSTITUTE(str old new) | strの中のoldをnewに置換して返す(COBOL 2023) |
WORKING-STORAGE SECTION.
01 WS-FIRST PIC X(10) VALUE 'TARO '.
01 WS-LAST PIC X(10) VALUE 'YAMADA '.
01 WS-FULL-NAME PIC X(30).
01 WS-TEXT PIC X(20) VALUE ' HELLO WORLD '.
01 WS-TRIMMED PIC X(20).
01 WS-LEN PIC 9(3).
PROCEDURE DIVISION.
*--- FUNCTION CONCATENATE: 文字列を連結 ---
MOVE FUNCTION CONCATENATE(
FUNCTION TRIM(WS-LAST TRAILING)
' '
FUNCTION TRIM(WS-FIRST TRAILING))
TO WS-FULL-NAME
DISPLAY WS-FULL-NAME *> 'YAMADA TARO'
*--- FUNCTION TRIM: スペース除去 ---
MOVE FUNCTION TRIM(WS-TEXT) TO WS-TRIMMED
DISPLAY '[' WS-TRIMMED ']' *> '[HELLO WORLD]'
*--- FUNCTION LENGTH: 文字列長 ---
MOVE FUNCTION LENGTH(WS-TRIMMED) TO WS-LEN
DISPLAY '長さ: ' WS-LEN
*--- FUNCTION UPPER-CASE / LOWER-CASE ---
DISPLAY FUNCTION UPPER-CASE('cobol 2024') *> 'COBOL 2024'
DISPLAY FUNCTION LOWER-CASE('COBOL 2024') *> 'cobol 2024'
STOP RUN.
FUNCTION TRIM(変数 TRAILING) は末尾スペースを除去し、LEADING は先頭スペースを除去します。省略すると両端を除去します。ただし結果はアルファベット型の一時領域に返るため、PIC X定義の変数にMOVEするか、DISPLAY/STRINGに直接渡して使います。
文字列長の扱い方とスペースの問題
COBOLのPIC X定義は固定長です。文字が短い場合、右側にスペースが埋まります。文字列操作でスペース処理を正しく扱わないと意図しない結果になります。
WORKING-STORAGE SECTION.
01 WS-NAME PIC X(20) VALUE 'NAKAMURA'. *> 後ろ12文字はスペース
01 WS-LEN PIC 9(3).
01 WS-MSG PIC X(40).
PROCEDURE DIVISION.
*> PIC句の全桁数(定義上の長さ)
MOVE FUNCTION LENGTH(WS-NAME) TO WS-LEN
DISPLAY '全桁数: ' WS-LEN *> '20'
*> 有効文字数(末尾スペースを除いた長さ)
MOVE FUNCTION LENGTH(FUNCTION TRIM(WS-NAME TRAILING)) TO WS-LEN
DISPLAY '有効長: ' WS-LEN *> '8'
*> 旧来の方法(INSPECT TALLYINGで末尾スペース数を数えて引く)
*> 現代COBOLではFUNCTION TRIMが簡潔でおすすめ
*> メッセージ組み立て
STRING '氏名: ' DELIMITED BY SIZE
WS-NAME DELIMITED BY SPACE
'さん' DELIMITED BY SIZE
INTO WS-MSG
DISPLAY WS-MSG *> '氏名: NAKAMURAさん'
実践パターン4選
CSV行の組み立て(WITH POINTERで追記)
ループで複数フィールドをCSV形式に結合するパターンです。WITH POINTERで位置を管理しながら追記します。
WORKING-STORAGE SECTION.
01 WS-CSV-LINE PIC X(200) VALUE SPACES.
01 WS-PTR PIC 9(3) VALUE 1.
01 WS-ORDER-DATE PIC X(8) VALUE '20240115'.
01 WS-CUST-ID PIC X(10) VALUE 'C00123'.
01 WS-ITEM-CODE PIC X(8) VALUE 'ITEM-001'.
01 WS-QTY PIC 9(5) VALUE 00010.
01 WS-AMOUNT PIC 9(9)V99 VALUE 15000.00.
01 WS-AMT-EDIT PIC ZZZ,ZZZ,ZZ9.99. *> 編集項目
PROCEDURE DIVISION.
MOVE 1 TO WS-PTR
MOVE SPACES TO WS-CSV-LINE
*> 日付
STRING WS-ORDER-DATE DELIMITED BY SIZE
',' DELIMITED BY SIZE
INTO WS-CSV-LINE WITH POINTER WS-PTR
*> 顧客ID(末尾スペースを詰める)
STRING WS-CUST-ID DELIMITED BY SPACE
',' DELIMITED BY SIZE
INTO WS-CSV-LINE WITH POINTER WS-PTR
*> 商品コード
STRING WS-ITEM-CODE DELIMITED BY SPACE
',' DELIMITED BY SIZE
INTO WS-CSV-LINE WITH POINTER WS-PTR
*> 数量(数値を文字として)
MOVE WS-QTY TO WS-AMT-EDIT
STRING FUNCTION TRIM(WS-AMT-EDIT LEADING)
DELIMITED BY SIZE
',' DELIMITED BY SIZE
INTO WS-CSV-LINE WITH POINTER WS-PTR
*> 金額
MOVE WS-AMOUNT TO WS-AMT-EDIT
STRING FUNCTION TRIM(WS-AMT-EDIT LEADING)
DELIMITED BY SIZE
INTO WS-CSV-LINE WITH POINTER WS-PTR
DISPLAY WS-CSV-LINE *> '20240115,C00123,ITEM-001,10,15,000.00'
STOP RUN.
日付文字列の整形(YYYYMMDD → YYYY-MM-DD)
数値型の日付をハイフン区切りの文字列に変換するパターンです。
WORKING-STORAGE SECTION.
01 WS-DATE-NUM PIC 9(8) VALUE 20240115.
01 WS-DATE-CHAR PIC X(8).
01 WS-DATE-FMT PIC X(10). *> YYYY-MM-DD
01 WS-YEAR PIC X(4).
01 WS-MONTH PIC X(2).
01 WS-DAY PIC X(2).
PROCEDURE DIVISION.
*> 数値日付を文字列に変換
MOVE WS-DATE-NUM TO WS-DATE-CHAR
*> 年・月・日に分割
MOVE WS-DATE-CHAR(1:4) TO WS-YEAR
MOVE WS-DATE-CHAR(5:2) TO WS-MONTH
MOVE WS-DATE-CHAR(7:2) TO WS-DAY
*> ハイフン区切りで結合
STRING WS-YEAR DELIMITED BY SIZE
'-' DELIMITED BY SIZE
WS-MONTH DELIMITED BY SIZE
'-' DELIMITED BY SIZE
WS-DAY DELIMITED BY SIZE
INTO WS-DATE-FMT
DISPLAY WS-DATE-FMT *> '2024-01-15'
STOP RUN.
ログメッセージの組み立て
バッチ処理でよく使うタイムスタンプ付きログを組み立てるパターンです。
WORKING-STORAGE SECTION.
01 WS-LOG-MSG PIC X(100) VALUE SPACES.
01 WS-TIMESTAMP PIC X(26).
01 WS-PROGRAM-ID PIC X(8) VALUE 'BATCHPGM'.
01 WS-MSG-BODY PIC X(60).
01 WS-REC-COUNT PIC 9(7) VALUE 1234567.
01 WS-CNT-EDIT PIC Z,ZZZ,ZZ9.
PERFORM LOG-OUTPUT
STOP RUN.
LOG-OUTPUT.
*> 現在日時取得
MOVE FUNCTION CURRENT-DATE TO WS-TIMESTAMP
*> CURRENT-DATEの形式: YYYYMMDDHHMMSSXX(16文字)+ タイムゾーン
*> カウントを編集
MOVE WS-REC-COUNT TO WS-CNT-EDIT
*> ログメッセージ組み立て
STRING WS-TIMESTAMP(1:4) DELIMITED BY SIZE *> YYYY
'/' DELIMITED BY SIZE
WS-TIMESTAMP(5:2) DELIMITED BY SIZE *> MM
'/' DELIMITED BY SIZE
WS-TIMESTAMP(7:2) DELIMITED BY SIZE *> DD
' ' DELIMITED BY SIZE
WS-TIMESTAMP(9:2) DELIMITED BY SIZE *> HH
':' DELIMITED BY SIZE
WS-TIMESTAMP(11:2) DELIMITED BY SIZE *> MM
':' DELIMITED BY SIZE
WS-TIMESTAMP(13:2) DELIMITED BY SIZE *> SS
' [' DELIMITED BY SIZE
WS-PROGRAM-ID DELIMITED BY SPACE
'] 処理件数: ' DELIMITED BY SIZE
WS-CNT-EDIT DELIMITED BY SPACE
'件' DELIMITED BY SIZE
INTO WS-LOG-MSG
DISPLAY WS-LOG-MSG.
*> 出力例: '2024/01/15 10:30:45 [BATCHPGM] 処理件数: 1,234,567件'
ヘッダー項目を動的に組み立てる(STRING + MOVE)
帳票の見出し行を条件によって変えるパターンです。
WORKING-STORAGE SECTION.
01 WS-HEADER PIC X(60) VALUE SPACES.
01 WS-REPORT-DATE PIC X(10).
01 WS-DEPT-NAME PIC X(20).
01 WS-REPORT-TITLE PIC X(30).
PROCEDURE DIVISION.
MOVE '2024-01-15' TO WS-REPORT-DATE
MOVE 'システム部' TO WS-DEPT-NAME
MOVE '月次売上集計レポート' TO WS-REPORT-TITLE
STRING WS-REPORT-DATE DELIMITED BY SPACE
' 作成' DELIMITED BY SIZE
' ' DELIMITED BY SIZE
WS-DEPT-NAME DELIMITED BY SPACE
' ' DELIMITED BY SIZE
WS-REPORT-TITLE DELIMITED BY SPACE
INTO WS-HEADER
DISPLAY WS-HEADER
*> '2024-01-15 作成 システム部 月次売上集計レポート'
STOP RUN.
よくある落とし穴と対策
| 落とし穴 | 問題の内容 | 対策 |
|---|---|---|
| 受け取り先の初期化忘れ | INTO変数を初期化しないと、前回の実行結果が残って文字化けが起きる | STRINGの前に必ず MOVE SPACES TO 受け取り変数 で初期化する |
| DELIMITED BY SPACEで途中に空白がある文字列 | “TANAKA JIRO” のような氏名をDELIMITED BY SPACEで渡すと”TANAKA”までしか転送されない | 途中にスペースを含む文字列はDELIMITED BY SIZEで渡し、有効長をFUNCTION TRIMで管理する |
| WITH POINTERの初期化忘れ | 2回目のSTRIN呼び出し時にWS-PTRを1に戻さないと、前回のPTR位置から書き込まれる | 新しいメッセージを組み立てる前は必ずMOVE 1 TO WS-PTR(またはMOVE SPACES TO バッファ)を実行する |
| UNSTRING後のTALLYINGカウンタ | TALLYINGはゼロ初期化されないため、ループ内でUNSTRINGを繰り返すと累積カウントになる | UNSTRINGの前に MOVE 0 TO TALLYINGカウンタ で初期化する |
| 数値のSTRING結合 | PIC 9定義の数値を直接STRINGに渡すと、ゾーン10進数の内部コードが転送され文字化けする | 数値はあらかじめ編集項目(PIC ZZZ9等)にMOVEして文字列化してからSTRINGに渡す |
WORKING-STORAGE SECTION.
01 WS-AMOUNT PIC 9(7)V99 VALUE 12345.60.
01 WS-AMT-EDIT PIC Z,ZZZ,ZZ9.99. *> 編集用
01 WS-AMT-STR PIC X(13).
01 WS-MSG PIC X(30).
PROCEDURE DIVISION.
*--- NG: 数値をそのままSTRINGに渡すと内部コードが転送される ---
*STRING WS-AMOUNT DELIMITED BY SIZE INTO WS-MSG. *> 文字化け
*--- OK: 編集項目を経由して文字列化する ---
MOVE WS-AMOUNT TO WS-AMT-EDIT *> 12,345.60 という編集済み文字列になる
MOVE WS-AMT-EDIT TO WS-AMT-STR *> X型変数に格納
STRING '金額: ' DELIMITED BY SIZE
FUNCTION TRIM(WS-AMT-STR LEADING) DELIMITED BY SIZE
'円' DELIMITED BY SIZE
INTO WS-MSG
DISPLAY WS-MSG *> '金額: 12,345.60円'
よくある質問
STRING 'PREFIX-' DELIMITED BY SIZE … のようにシングルクォートで囲んだリテラルを直接USING句に書けます。定数として使う区切り文字や固定テキストをわざわざ変数に入れなくてよいので、コードが簡潔になります。まとめ
COBOLの文字列操作は専用命令が担当します。それぞれの役割をまとめます。
| 機能 | 説明 |
|---|---|
| STRING文 | 複数の文字列を1つに結合する。DELIMITED BY SIZE/文字の使い分けが重要 |
| WITH POINTER | STRING文の書き込み位置を管理する。追記パターンに必須 |
| ON OVERFLOW | STRING文で受け取り先の容量超過を検知する |
| UNSTRING文 | 1つの文字列を区切り文字で分割して複数変数に振り分ける |
| INSPECT文 | 文字のカウント(TALLYING)・置換(REPLACING)・変換(CONVERTING)を行う |
| FUNCTION CONCATENATE | COBOL 2002以降で使える文字列連結関数。TRIM/UPPER-CASE等も合わせて使う |
| 数値の文字列化 | 数値型は編集項目(PIC ZZZ9等)を経由してから文字列操作に使う |
文字列の初期化を忘れず、数値は編集項目を経由させるという2点を守るだけで、多くのバグを防げます。
COBOLのデータ転送の基本はMOVE文の完全ガイドで、画面への出力方法はDISPLAY文の使い方で解説しています。変数の初期化についてはINITIALIZE文のガイドも参照してください。