🧩今日の学び
・IF OR は「どれかひとつでも空欄なら即アウト」の実務的バリデーション。
・CNT-BLANKは“何個空いてるか”ではなく“空欄あったか”のフラグ扱いだと係長が喝。
・次回は「AND条件」や「詳細バリデーション」へ踏み込み、入力検証の本質へ近づく。
今日のコード
*> 必須チェック(空欄)
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.
MOVE ZERO TO CNT-BLANK
なるお)CNT-BLANKはバリデーション用とか言ってたけど、ブランク、空欄数えるよーってやつに0入れるってか?
いつものゴミ箱を空にするあれね。
係長)だいぶ理解してきたな。
そうだ、CNT-BLANK は「必須項目が空欄だったらカウントするための変数」だ。
な)でしょでしょ!係長抜かれる心配して寝れないでしょ!胃痛に悩まされてるでしょ!でも入院しちゃだめっすよ!
空欄チェックの真実:CNT-BLANKの役割
係)「まず空欄数はゼロからスタートね」ってゴミ箱リセットの動きからだ。
もし初期化しなかったら、前のレコードで空欄が見つかって CNT-BLANK=1 になってたのが、次のレコードにまで持ち越されて「空欄なくてもエラー扱い」ってバグになる。
ようやく考え方に慣れてきたみたいだな。
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がでてきたけど…
F-ORDER-DATE-A がスペースはいってて、orだから「それか」F-ORDER-ID-A にスペースが入っててが続くと ADD 1 TO CNT-BLANKを1を追加するってなってると?
え、なにこれ、それか一つでもスペースなら、CNT-BLANKを1プラスだと。なんでスペースは入ってたら、一つ追加したら…CNT-BLANKが0からスタートしているので、1ずつ追加される……
なにこれ?どういうこと?
IF OR:ひとつでも空欄なら即アウトの仕組み
係)これは「複数条件を OR でつないで、ひとつでも真なら中の処理をやる」ってこと。
つまり 必須項目のどれかが空欄なら ADD 1。
な)それはいいんすけど、どっかに一つ空欄ありますって言われてもって感じがするんですけど?
係)そうだな、この書き方だと「どれが空欄だったか」は分からねえ。
分かるのは「なんか空欄あるんだな」って事実だけ。
でも次に
IF CNT-BLANK > 0
MOVE "MISSING REQUIRED FIELD" TO WS-MSG
PERFORM WRITE-ERROR
EXIT PARSE-AND-VALIDATE
END-IF.
こうなってただろ?
要は「必須項目がひとつでも空いてたらアウト。細かい理由はどうでもいい。エラー行き」って設計なんだ。
な)えー、でも「注文日が空欄」とか「税率が空欄」とか、ちゃんと理由ほしくないっすか?
係)そりゃほしい場面もある。けどCOBOLでそれ全部やると条件分岐だらけになってコードがクソ長くなるからな。
実務では「時間と納期」と「どこまで精密なエラーが要るか」のトレードオフだな。
でも「最低限の必須項目がそろってなきゃ処理できねー」って要件は満たしてるだろう?
な)じゃあ名前がCNT(カウント)って付いてるけど、ほんとは「FLAG」とかのほうが正解なんじゃ…?
係)………。
な)あ、係長の顔が曇った!!これ禁句パターンっすか? (ニヤニヤ)
係)気づいてんなら黙っとけ。昔のプログラマは「とりあえずCNTって付けとけ」っていう雑な文化があったんだよ。
ほんと、余計なこと「だけ」は見えるんだな。
な)”MISSING REQUIRED FIELD” を WS-MSG に入れてー WRITE-ERROR 実行だ!
そうするとPARSE-AND-VALIDATE.で初期化されるってことっすよね?
そうしたまた0からカウントしていくみたいな?
係)間違ってはいないんだが…もうちょっとちゃんと説明できないのかお前。
- CNT-BLANK は最初に MOVE ZERO でリセットされる。
- もし必須項目のどれかが空欄なら ADD 1 TO CNT-BLANK で「はい、欠けてますよ」って印を付ける。
- CNT-BLANK > 0 なら “MISSING REQUIRED FIELD” を WS-MSG に入れて PERFORM WRITE-ERROR。
- EXIT PARSE-AND-VALIDATE で、そのレコードの処理はそこで打ち切り。
次のレコードが来たらまた最初に CNT-BLANK をゼロに戻すから、前の行のエラーは持ち越さないといかん。
EXITで打ち切り?ループの流れを整理する
な)えーでも、PARSE-AND-VALIDATEをEXITとなると、PERFORMされたPARSE-AND-VALIDATEから抜けちゃうわけで、だったら、初期化されないんじゃないんですか?
係)落ち着け。挙動を順で追え。
そうしないと、今何をしているのか把握しておかないとわけわからなくなるぞ。
今はこういう流れの中にいる。
ループで1行読む → PERFORM PARSE-AND-VALIDATE
段落の先頭で MOVE ZERO TO CNT-BLANK(初期化)
必須項目チェック
空欄があれば CNT-BLANK = 1
→ メッセージ入れて WRITE-ERROR
→ EXIT PARSE-AND-VALIDATE(このレコードの検証はここで打ち切り)
呼び出し元(READ-INFILE → PROCESS-LOOP)に戻る
次のレコードを読み込む
また PERFORM PARSE-AND-VALIDATE → 先頭の初期化がもう一度走る
な)あそっか、今ループ中なんでしたっけ。
こうやって一つずつ考えるのはそこだけはわかりやすいんですけど、今何してんのかわからなくなります…
これだからCOBOLの家はって言われるんすよ…
係)COBOLは「読むだけで意味がわかるように」って設計思想のくせに、長ったらしくて今どこを処理してんのか迷子になりやすいんだよ。
でもな、整理するとシンプルだ。
今やってんのは大きく分けて―
- 1行読む(READ-INFILE)
- 分解する(PARSE-AND-VALIDATE)
- 初期化
- 必須チェック
- 数値チェック
- 変換&計算
- 集計&出力
- ファイル終わったらFINISHでまとめ出力
このサイクルを繰り返してるだけだぞ。
おむすび
な)うー。簡単にまとめられるとなんか悔しー。
係)お前が俺の上に行けるとか、生きてるうちに感じさせてくれ。
な)きぃぃ!!
おれは一食で米2合食えますからね!係長食えないでしょ!
係)なんの自慢だよ…
な)勝った!
係)だからデブなんだな。
な)きぃ!!
係長のワンポイト
必須項目チェックは「ひとつでも空欄ならアウト」という設計だ。
CNT-BLANK は “何個空欄か” ではなく “空欄あったか” を示すフラグ扱い。
OR でつないでいるのは「どれか1つでも空欄なら真」にするため。
EXIT PARSE-AND-VALIDATE は、その行の処理を即座に打ち切るだけ。
次のレコードに進むと、CNT-BLANK は先頭で毎回ゼロに戻るぞ。

コメント