🧩今日の学び
・INSPECT…TALLYING でアルファベット混入を即検出できる仕組みを理解。
・係長いわく「BY と FOR ALL の違い」が今回の真のキモ。
・データ検証は“空欄 → 文字混入 → 数値チェック”の三段階で見る癖をつけよう。
今日のコード
*> 数値チェック(英字混入をざっくり検出)
MOVE ZERO TO CNT-ALPHA
INSPECT F-QUANTITY-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
INSPECT F-UNIT-PRICE-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
INSPECT F-TAX-RATE-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
IF CNT-ALPHA > 0
MOVE "NUMERIC PARSE ERROR" TO WS-MSG
PERFORM WRITE-ERROR
EXIT PARSE-AND-VALIDATE
END-IF.
なるお)あれ、なんか見たことなうような。
これは・・・デジャヴですね!
視野が広いから見える力が強いんですよ俺!霊感強いんですよ!幽霊見たことないですけど!
見直しました?見直しましたよね!
デジャブの正体はINSPECTだった
係長)いや、デジャヴでも霊感でもねぇよ。前にちょろっと話した INSPECT … TALLYING がここで本番登場してるだけだ。
な)あれそっち?
*> 必須チェック(空欄)
MOVE ZERO TO CNT-BLANK
IF F-ORDER-DATE-A = SPACES OR
F-ORDER-ID-A = SPACES OR
F-QUANTITY-A = SPACES OR
F-UNIT-PRICE-A = SPACES OR
F-TAX-RATE-A = SPACES
ADD 1 TO CNT-BLANK
END-IF.
IF CNT-BLANK > 0
MOVE "MISSING REQUIRED FIELD" TO WS-MSG
PERFORM WRITE-ERROR
EXIT PARSE-AND-VALIDATE
END-IF.
前回のこれかとおもったのは違ったです?
必須チェックと数値チェック:似て非なる二段構え
係)ああ、なるほどな。見た目が似てるからデジャヴ感じたんだろ。
前回のこれは 「必須チェック(空欄)」。
「そもそも入ってなきゃダメな項目が空欄ならアウト」ってやつだな。
今回のは 「数値チェック」。
「一応値は入ってるけど、数字のはずの場所にアルファベットが混じってたらアウト」っていう次のステップだ。
な)え、つまり前回は「空じゃダメ」、今回は「変なアルファベットが混ざっててもダメ」ってことっすか?
係)そういうことだ。順番にフィルターかけて、空欄落として、次に文字混入落として、それでも残ったのだけが「まともなデータ」って扱いになる。
な)そうか!そうやって人類がフィルターにかけられていって、俺みたいな天才が残っていく感じですね!
納得です、深い深海のごとく納得なのです。
係)そうだな、ザルの網目に残った米粒と言えるな。
な)お米一粒に神様は宿りますもんね!神様に昇格ですね!INSPECT GODNESSですね!
係)どんだけ前向きなんだよ…
だから、そんなことはどうでもいいんだよ!
な)神に向かって!?
係)……
「このフィールドの中にアルファベットが混じってたら数えろ」っていう処理だ。
な)何の話ですか?
係)お前な!
な)神は殴られるのを拒否!
係)世が世ならお前の顔を変えられたのにな。
な)ひぃ!!
*> 数値チェック(英字混入をざっくり検出)
MOVE ZERO TO CNT-ALPHA
INSPECT F-QUANTITY-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
INSPECT F-UNIT-PRICE-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
INSPECT F-TAX-RATE-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
IF CNT-ALPHA > 0
MOVE "NUMERIC PARSE ERROR" TO WS-MSG
PERFORM WRITE-ERROR
EXIT PARSE-AND-VALIDATE
END-IF.
係)「このフィールドの中にアルファベットが混じってたら数えろ」っていう処理だ。
な)さっきも言いませんでした?デジャブ!?
係)……お前聞く気あるのか?
な)ひっ!ありますよ!もちろんあります!
頭の天辺から地球のコアを超えて、ブラジルまで。
あ、実は日本の裏側ってブラジルじゃないって知ってまし……
いいえ、なんでもないです…
(凄まじい顔で睨まなくても…)
MOVE ZERO TO CNT-ALPHA
係)さすがにこれはもういいだろ?
な)わかりますよ!
CNT-ALPHAに0を入れると。
係)そうだな
INSPECT F-QUANTITY-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
そして、数量欄の文字列に「A」とか「B」とか入ってたら、そのぶん CNT-ALPHA に足される。
で、もし CNT-ALPHA > 0 だったら「数字のはずなのに文字が混じってるじゃねーか!」ってことで、エラー扱いして WRITE-ERROR に飛ばす。
な)ふむふむ
INSPECT F-QUANTITY-A TALLYING CNT-ALPHA FOR ALL ALPHABETIC.
TALLYINGは数えるって感じです?
係)それでいいぞ。
な)ALPHABETICって?
係)ALPHABETIC ってのは COBOLの条件名キーワードだ。
ALPHABETICを数える仕組み:TALLYINGの真価
ざっくり言うと「その文字が A~Z のアルファベットかどうか」って判定に使える。
INSPECT F-QUANTITY-A
TALLYING CNT-ALPHA FOR ALL ALPHABETIC
って書いたら、F-QUANTITY-A の中に A~Z が入ってたら、それを **「アルファベット文字」**としてカウントして CNT-ALPHA に足す。
な)じゃあ “123ABC” とか入ってたら、「A」「B」「C」で 3 が足されるってことっすね?
係)その通り。数字は数えないし、スペースや記号も ALPHABETIC には含まれない。純粋に A~Z だけだ。
な)あれ?ALLってBYじゃなかったでしたっけ?
係)お前、記憶力がスライド式黒板ぐらいしかないな。さっき上げたと思ったら、すぐ下に隠れてる。
UNSTRING IN-REC DELIMITED BY ALL ","
まったくもう一回いくぞ。
「DELIMITED BY ALL ‘,’」の BY は「区切り文字を指定する」って文脈だったろ。
今回の FOR ALL ALPHABETIC は「この対象文字を片っ端から数えろ」って命令。
つまり、
- BY …「何で切るか」
- FOR ALL …「何を数えるか」
役割が違うんだよ。
な)はえー。
そしてその次のところはっと、
IF CNT-ALPHA > 0
MOVE "NUMERIC PARSE ERROR" TO WS-MSG
PERFORM WRITE-ERROR
EXIT PARSE-AND-VALIDATE
END-IF.
CNT-ALPHAが1以上になってたら、ってことは、数字以外が混入してたら、、、
MOVE "NUMERIC PARSE ERROR" TO WS-MSG
NUMERIC PARSE ERRORをWS-MSGに入れ込んじゃって、WRITE-ERRORを実行だ!でも、PARSE-AND-VALIDATEから離脱となっているので、、、どっかに戻ると…
係)そうそう、その「どっか」が大事なんだよな。
いまコードの流れはこうだ。
- PROCESS-LOOP が「EOFになるまで繰り返すぞ」と構えてる。
- 1行読む → PARSE-AND-VALIDATE を PERFORM。
- もしエラーだったら MOVE “NUMERIC PARSE ERROR” TO WS-MSG して PERFORM WRITE-ERROR。
- そのあと EXIT PARSE-AND-VALIDATE で、その段落の残り処理をすっ飛ばして終了。
- 呼び出し元(PROCESS-LOOP)に戻る。
つまり、「エラー出した行はそこで処理終了、次の行を読み込め」っていう流れだ。
おむすび
な)はー、離脱って言っても、この世界線から離脱できないんですね。
あれ?じゃあ俺がEXITしても、結局また明日会社来るんすか?
現実から離脱できないじゃないですか!?
係)俺が退職願出しておくから、もう来なくていいぞ。
係長のワンポイント
INSPECT … TALLYING FOR ALL ALPHABETIC は「数字のはずの場所に A〜Z が混ざっていないか一気に数える」処理だ。
CNT-ALPHA は “何個混入したか” を示す指標で、1つでもあれば即アウト。
必須チェック → 数値チェックの順でフィルターを重ねるのが COBOLの定石。
EXIT PARSE-AND-VALIDATE は“段落を抜けて次の行へ進む”だけで関数脱出ではない。
つまり「変な文字が混じるだけで即切り捨て、次のレコードへ」が今回の流れだ。

コメント