【COBOL 書き1-8-7】TEST-NUMVAL関数で桁数を無視させろ!〜コーラ怖い

🧩今日の学び
PIC X(3)の入力は空白で埋められるため、見た目の値と実際の中身は異なる
IS NUMERICは厳密すぎるため、現実の入力には合わないケースがあり、TEST-NUMVALで位置特定し判定するのが有効
・COBOLは値そのものではなく「中身の構造」で評価する言語である

係長)なんでそうなったかわかったか?バタフライエフェクト起きたんだろ?

なるお)ほんと性格悪いっすよね…

係)お前が言ったんだろうが!発言に責任持てよ(ニヤニヤ

な)その顔でニヤニヤしてたら、追い込みかけて楽しんでるヤバい人ですからね。

係)わるかったな…

な)えーと…、なんでってのがわからないけど、3桁用意したけど、1を入れたら、001が入っているわけっすよね?

それが数字に変換されたから、001になってるんじゃないんすか?

てか1を入れたら、なにか起きてたんすかね?

係)まず、3桁の数字入れてみろ。

な)へ? へい

💻 ターミナル出力 実行結果
IRERO
111
IRERO
222
IRERO
333
IRERO
=
00666

え!?なにこれ!?計算されてますけど!?

係)それがヒントだぞ。

な)いや、HINT MORE!

…当然スルーっすね…、うーん、2桁だったらどうなるのこれ?

💻 ターミナル出力 実行結果
IRERO
11
ERROR ZANEN ENTER SUJI!!
IRERO
22
ERROR ZANEN ENTER SUJI!!
IRERO
33
ERROR ZANEN ENTER SUJI!!
IRERO
=
00000

あいやー。だめでやんの。

1桁と2桁が同じくだめなのに、3桁は行けるってことは、PIC X(3)が何か悪いことしてる、極悪人だってことすかね…。

係)そこまできたなら、説明していくぞ。

な)あ!極悪人代表の人!

係)なにぃ!?

な)いえ…お願いします…

PIC X(3)は空白で埋められている

係)01 Y PIC X(3). という「3文字分の箱」に「1」だけを入れてエンターを押すと、残りの2文字分を空にはできないので、勝手に 半角スペース が埋められているんだよ。

つまり、箱の中身は "1 " になってるというわけだ。

な)あー、余計なお世話君…

あ!ってことは001とか入れればいいってことっすよね!LET’S GO!

💻 ターミナル出力 実行結果
IRERO
001
IRERO
002
IRERO
003
IRERO
=
00006

ぎゃー!!きたー!!

係)ほんとうるっさいな…

な)もうこの計算機にうっとりです。もう卒業式でいいです。「仰げば尊し」斉唱しちゃいましょうか!歌詞知らないっすけど。

係)まだ桁数不足が解決されてないだろ!なにが卒業だよ。幼稚園からやり直してこいよ。

な)そこまで!?

係)いいか、これは作った者にとっては、3桁で入力するってことがわかるが、それ以外の者にとっては、そんなことわからないだろ。

そこでだ、一つ関数を紹介するぞ。

IS NUMERICは厳しすぎる判定だった

まず、IF Y IS NUMERIC という条件式は「箱の端から端まで、1ミリの隙間もなく全部が数字か」という超スパルタな判定をするんでな、スペースを見つけた瞬間に「数字じゃない!」と弾いてしまう。

な)ほー

係)その次にあるFUNCTION NUMVAL(Y) という関数は、「スペースが混じってても無視して数字にしてくれる」んだ。

つまり、IS NUMERIC のスパルタ判定から別の判定にできれば、1でも12でも普通に計算できる」わけだ。

それを可能にするのがTEST-NUMVALという関数だ。

な)ほー

係)つまり、わかるな?

な)はい、わかりません。

係)なんでだよ!

な)いやいやいやいや、何がわかるってんすか!?

係)だから、考えてみろって言ってんだよ!

な)むーん…、今がこうで、NUMVALさんは無理矢理にでも数字に変換してくれるんでしょ?

📝 COBOL sum.cob
    ELSE
        IF Y IS NUMERIC
            MOVE FUNCTION NUMVAL(Y) TO X
            ADD X TO TOTAL
        ELSE 

ってことは、IS NUMERICで数字じゃない判定されて、ELSEに行っちゃたってことよね。

ってことは、IS NUMERICが犯人じゃないすか、犯沢さんじゃないすか。

係)だからIS NUMERICではなくて、TEST-NUMVAL使えっていう話だよ。

な)あ、そゆこと…

TEST-NUMVALにするってんだから…これでいいんすか?

📝 COBOL 変更?
    IF Y = "="
        CONTINUE
    ELSE
        IF FUNCTION TEST-NUMVAL(Y)
            MOVE FUNCTION NUMVAL(Y) TO X
            ADD X TO TOTAL
        ELSE 

係)これだと条件になってないだろ?

な)条件って、数字かどうかってこと?ってTEST-NUMVALが数字かどうかを表してくれるんじゃないんす?

係)TEST-NUMVALが数字かどうかってことを確認しないとならないだろ?

な)数字かどうかって…、だって数字じゃないんすか?

係)この関数TEST-NUMVALは「犯人の居場所」を突き止めてくれるんだよ。

な)犯人?係長じゃないんすか?

係)なんでだよ!犯沢さんとか言ってただろ!

いいか、FUNCTION TEST-NUMVAL(Y) という関数は、箱の中身を左から順番に調べていくんだよ。

な)左から?

係)そうだ。例えば、さっきお前が1を入力したら、数字入れろって怒られただろ?

それは”1■■“という文字が入ったからだ。■はスペースな。

お前がPIC X(3)と宣言したから、3桁の箱が出来上がったわけだが、一文字だけだったから、COBOLが気を利かせて足りない桁を補って、”1■■“となってしまったがために、NUMERICは「それは数字ではない」って判断をしたってわけだ。

な)ふみみ…

係)その証拠に、そのあと001を入力したら数字として認識されて計算されたろ?

な)あー

係)そのうえでもう一度さっきの話だ。

FUNCTION TEST-NUMVAL (Y) は、引数Yを左端から評価していく関数だ。

したがって、「戻り値が 0 (エラーなし)であること」が、数字としての妥当性を担保する条件式になるわけだ」

な)むーん…

係)例えば、お前が01 Y PIC X(3). の箱にこんな入力をしたとして,

  • 入力 "1" (これだと、1とスペース2つとなる
    • TEST-NUMVAL の結果:0 (スペースは無視できるからエラーなし!)
  • 入力 "12A" (最後にAを入れた)
    • TEST-NUMVAL の結果:3 (3文字目の『A』がおかしい!)
  • 入力 "X55" (最初にXを入れた)
    • TEST-NUMVAL の結果:1 (1文字目の『X』がおかしい!)

という意味合いになるので、IF FUNCTION TEST-NUMVAL (Y) = 0だと数字だから真として次に進んでよし!ってなるわけだ。

な)ほむむ。

係)わかったか?

な)なんとなく…

順番に見ていって、TEST-NUMVALが数字じゃない「とこ」を教えてくれるから、それを利用すれば、「(0だったから)数字」か「(0じゃなかったから)数字じゃない」かを判定できるってことっすか。

係)お、いいな!

そういった利用はExcelでもすることあるだろ?

な)あーそっすね。0で合計との計算ミス確認したりするアレっすね。

係)よし、つまりどうなる?

な)は?何の話?

係)コードだよ!

な)あ、いまコード書いてたんでしたっけ…。

つまり、Yを検査したら何もなかったから0であればいいってことだから、= 0でいいんじゃないっすか?

📝 COBOL 変更後
    IF Y = "="
        CONTINUE
    ELSE
        IF FUNCTION TEST-NUMVAL(Y) = 0
            MOVE FUNCTION NUMVAL(Y) TO X
            ADD X TO TOTAL
        ELSE

係)よし全体整理して実行してみろ。

な)あい…

📝 COBOL sum.cob
  1IDENTIFICATION DIVISION.
  2PROGRAM-ID. CALC-SUM.
  3
  4DATA DIVISION.
  5WORKING-STORAGE SECTION.
  6
  701 X PIC 9(3) VALUE 0.
  801 TOTAL PIC 9(5) VALUE 0.
  901 Y PIC X(3).
 10
 11PROCEDURE DIVISION.
 12
 13PERFORM UNTIL Y = "="
 14
 15    DISPLAY "IRERO"
 16    ACCEPT Y
 17
 18    IF Y = "="
 19        CONTINUE
 20    ELSE
 21        IF FUNCTION TEST-NUMVAL(Y) = 0
 22            MOVE FUNCTION NUMVAL(Y) TO X
 23            ADD X TO TOTAL
 24        ELSE
 25            DISPLAY "ERROR ZANEN ENTER SUJI!!" 
 26        END-IF
 27    END-IF
 28
 29END-PERFORM
 30
 31DISPLAY TOTAL.
 32STOP RUN.

で、実行っと…で、1, 2, 3と入れていって=入れると…

みぎゃああああ!

💻 ターミナル出力 実行結果
IRERO
1
IRERO
2
IRERO
3
IRERO
=
00006

か、か、係長!00006って出ちゃいました!!

係)だから当たり前だろ!!

な)ひぃ!ちゃんと動くなんて怖いー

係)何が怖いんだよ!

な)ここらで一杯コーラが怖い

係)…………ふざけんなよ。

な)ひっ!

係長のワンポイント

入力は見た目どおりの値じゃない。
箱の中身(スペース含む)で評価される。
IS NUMERICは厳密すぎて、現実の入力には合わないこともある。
だからTEST-NUMVALで「どこまで正常か」を見て判断する。
COBOLは値ではなく、“中身の構造”を見て処理する言語だ。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

CAPTCHA