こんにちは!メインフレームの世界へようこそ。
JavaやCOBOLといった他のプログラミング言語の経験がある方にとって、IBMメインフレームの世界、そしてそこで長年君臨してきた「PL/I(ピーエルアイ)」は、最初は少し近寄りがたい要塞のように見えるかもしれません。「なんだか書き方が独特だな…」「データの持ち方が厳しそう…」と、不安になりますよね。
でも、安心してください。一見すると呪文のように見えるPL/Iのルールも、一つひとつ紐解いていけば、実はとても合理的でプログラマの意図に忠実に動いてくれる可愛い奴なんです。
今回は、そんなPL/Iの数ある機能の中から、帳票出力やファイル作成の現場で避けて通れない「ピクチャ編集文字 ‘Z’ によるゼロ抑制(Zero Suppression)」を、優しく、そして徹底的に解説していきたいと思います。
—
1. なぜ「0」が消える?ピクチャ編集の役割とは
JavaやC言語で画面やファイルに数値を出力するとき、例えば「5」という数字を「00005」と出すか、あるいは「 5」と左側にスペースを空けて見やすくするかは、フォーマット関数を使って簡単に指定できますよね。
PL/Iの世界でも、コンピュータ内部で計算に使う「純粋な数値データ」と、人間が画面や帳票で読むための「文字(キャラクタ)データ」は全く別物として扱われます。
内部の数字をそのまま印刷すると、例えば `123` というデータが `0000000123` のように、上位の使っていない桁まで「0」で埋め尽くされて出力されてしまうんです。昔の銀行の通帳や請求書を思い浮かべてみてください。「0000123円」なんて書いてあったら、ちょっと読みにくいしカッコ悪いですよね。
そこで登場するのが、ピクチャ(PICTURE)句です。
「このデータをこういう見た目に飾り付けて出力してね!」と指示するための専用の型で、その飾り付けの主役こそが、今回取り上げる ‘Z’ なのです。
—
2. 魔法の文字 ‘Z’ の正体と、COBOLとのちょっとした違い
ピクチャ句の中で使われる ‘Z’ は、「Zero(ゼロ)を空白(Space)に置き換える(Suppressする)」 という意味を持っています。
COBOLを触ったことがある方なら、「あぁ、COBOLの `Z` 編集句と同じね」とピンと来たかもしれません。その通り、基本の考え方は一緒です。しかし、PL/IにはPL/Iなりの、少しユニークで強力なルールがあります。
‘Z’ の基本的なルール
- 数値の先行ゼロ(意味のない左側のゼロ)の位置に ‘Z’ を配置すると、その部分が「0」だった場合に半角スペース(空白)に置き換わります。
- ただし、有効数字(意味のある数字)にぶつかるか、小数点に到達するまでしかゼロは消えません。途中で消え方が止まる仕組みになっています。
言葉だけだとイメージしにくいので、実際にPL/Iのコードを見てみましょう!
—
3. 実践!PL/Iコードで見るゼロ抑制の動き
以下のサンプルプログラムを見てください。実務のバッチ処理を想定した書き方になっています。(PL/Iのキーワードは大文字で書くのが伝統的でカッコいいとされています!)
STG: PROC OPTIONS(MAIN);
/ — 変数の宣言 — /
/ 内部計算用の固定小数点数(5桁) /
DCL WK_IN_NUM FIXED DEC(5,0) INIT(123);
DCL WK_ZERO_NUM FIXED DEC(5,0) INIT(0);
/ 出力編集用のピクチャ変数(文字型として扱われます) /
/ ‘ZZZZ9’ は「下1桁は0でも残す、それより上はゼロ抑制する」という意味 /
DCL OUT_EDIT_1 PICTURE ‘ZZZZ9’;
DCL OUT_EDIT_2 PICTURE ‘ZZZZZ’;
/ — データの編集(代入するだけで自動変換されます) — /
OUT_EDIT_1 = WK_IN_NUM;
OUT_EDIT_2 = WK_ZERO_NUM;
/ — 結果の確認(DISPLAYはコンソールに出力します) — /
PUT SKIP EDIT (‘編集結果1 (123をZZZZ9へ): [‘, OUT_EDIT_1, ‘]’) (A, A, A);
PUT SKIP EDIT (‘編集結果2 ( 0をZZZZZへ): [‘, OUT_EDIT_2, ‘]’) (A, A, A);
END STG;
このコードを実行するとどうなる?
コンソール(SYSOUT)には、次のように出力されます。
編集結果1 (123をZZZZ9へ): [ 123]
編集結果2 ( 0をZZZZZへ): [ ]
おっ、見事にスペースに置き換わっていますね!
- `編集結果1` では、元の値 `123` に対して `ZZZZ9` を指定したため、上位の2桁分のゼロが綺麗に空白に変わり、` 123` という右詰めの綺麗な文字列になりました。最後の `9` は、「たとえ値が0であっても、この桁の数字は絶対に隠さず(抑制せず)そのまま表示しなさい」というアンカー(錨)の役割を果たします。
- `編集結果2` では、すべてを `Z` にした変数に `0` を代入しました。この場合、すべてが空白になり、完全なブランク文字列(` `)として出力されます。「金額が0円の時は何も表示したくない」といった要件で非常によく使われるテクニックです。
—
4. 初学者がハマりやすい「落とし穴」とアドバイス
レガシーシステムの移行や保守をしていると、「あれ?思った通りにゼロが消えないぞ…」と頭を抱える場面に遭遇することがあります。ここで、現場の先輩たちがよく躓くポイントをこっそりシェアしておきますね。
① ピクチャ変数は「文字」であり「数字」ではない!
ここが一番重要です。`PICTURE` 属性を持つ変数は、見た目は数字を扱っているように見えますが、内部的には文字(CHARACTER)データとして扱われます。
そのため、ピクチャ変数同士でそのまま四則演算(足し算や引き算)を行うと、コンパイルエラーになるか、予期せぬデータ例外(S0C7などのアベンド)を引き起こす原因になります。
「計算は `FIXED BINARY` や `FIXED DECIMAL` で行い、画面やファイルに出力する直前の最終ステップで `PICTURE` 変数に代入する」 これがPL/Iプログラミングの鉄則です。
② 桁あふれ(オーバーフロー)に注意
例えば、`PICTURE ‘ZZZ9’`(4桁分)の変数に対して、`10000`(5桁の数字)を代入しようとすると、入り切らない上位の桁が切り捨てられたり、データ例外を起こしたりします。出力先のピクチャ句のサイズは、想定される最大値の桁数を必ずカバーできるように設計しましょう。
—
おわりに
いかがでしたでしょうか?
PL/Iのピクチャ編集文字 `Z` によるゼロ抑制は、最初は独特の記法に戸惑うかもしれませんが、「出力の見た目を整えるための優しい相棒」だと思えば、怖くありませんよね。
JavaやCOBOLで培ったプログラミングの基礎的なセンスがあれば、PL/Iの仕様もすぐに自分のものにできます。レガシーシステムの海原へ漕ぎ出すあなたを、私は心から応援しています。
日々の開発やマイグレーション作業、大変なこともあるかと思いますが、一つひとつ紐解いていけば必ず道は開けます。マイペースに頑張っていきましょう!
