【COBOL 書き1-12-8】改行の仕様からIS NUMERICで解決!〜クーニャンは飲めるのか?

係長)・・・

なるお)いやー、ひと仕事終わったあとのクーニャンは格別でしょうね!

係長)そうじゃなくて、全く気づいてないのか?

な)鳥貴族にクーニャンがないこと?

係)違うわ!

な)なんですの…

係)この結果見てなんとも思わなかったのかってことだよ。

な)曇りなき結果じゃないっすか…

係)どう考えても曇ってるだろ!

いいか、これもたまたま結果が正解だったってだけだ。

つまり、どこかに欠陥があるんだよ!

な)でも、うっとり的な…

係)いいから、実行結果を確認してみろ!

中央値は正しいのに件数が合わない

💻 ターミナル出力 実行結果
COUNT=07 LOW-POS=03 HIGH-POS=04
LOW-VAL=00900 HIGH-VAL=01500
MEDIAN IS 01200.0

な)このうっとり結果の何が問題なんすか…

むー ………

あれ、COUNT=07? データは6つだったよね?

📝 COBOL naruo2.txt
2025-12-31hoshiimo            02500
2026-01-01gyudon2             00900
2026-01-01curry               01500
2026-01-02gyudon2             00900
2026-01-03hoshiimo            02500
2026-01-04udontenpura         01800

やっぱデータは6個だわ

だったら、COUNT=06だよね…え、どういうこと?

係)ようやく気づいたかよ…

な)なんでこうなるの?

係)これはわかっていないとハマる沼だ。

な)え?じゃ、オレの責任じゃない?

係)お前の責任ではないと言いたいところではあるが、それを前提として作っておくべきことだ。だから、お前の責任だな。

な)あまりにもひどい!

cat -eで最終行の改行を確認する

係)いいから、ターミナルでcat -e naruo2.txtと打ってみろ。

な)猫?

💻 ターミナル出力 実行結果
2025-12-31hoshiimo 02500$
2026-01-01gyudon2 00900$
2026-01-01curry 01500$
2026-01-02gyudon2 00900$
2026-01-03hoshiimo 02500$
2026-01-04udontenpura 01800%

全然猫じゃない!?

係)猫が出てくる余地がどこにあるんだよ…

改行の有無でカウントが変わる

いいか、ここの最後のudon tenpuraの行の最後だけ違うのわかるか?

な)あー%になってますね

いきなり割って100掛けたくなった気分なんすかね。

係)誰がどんな気分になるんだよ!

いいか、ターミナル上において、$ は改行(行の終わり)が入っているという表示で、% は行が終わってない(改行なし)って表示になる。

な)ふむふむ…、でも、だったら、最後が%は改行してないんだから、6になって、$は改行したんだから、7になるんじゃないんすか?

係)まぁ、そう思うだろうな。

いいか、改行は改行しただけであって、行の先頭にデータなければ、その行はデータなしで処理される。

反対に、改行なしの場合、改行無しじゃずっとデータを探してしまうことを避けるために、COBOLが改行を入れてくれるんだ。その行にデータが入っている形でな。

つまり、改行あり($)の場合、次の行がないため、カウントは6行目で止まって、COUNT=6となる。

改行なし(%)の場合、次の行が勝手に現れたため、カウントは一つ増えてCOUNT=7になったというわけだ。

な)むむん、って、こぼるんの余計なお世話の強要じゃないっすか。これ!

係)だからこそファイルについては、明確な規則が必要だって話だ。データの作成形式、保存形式、読込形式などだ。

誰が使うかわからないんだ。その対策はしておく必要があるぞ。

な)めんどくさ!てか、つくもめんどくさ!

係)はぁ?

な)え、七面倒くさいの強化版ですけど?九十九面倒くさいって

係)そうなのか?

な)知らんすけど?

係)知らねーのかよ!

な)でも、そんなのどうやって解決するんすか…

だって、見た目で言えば、改行入ってないんだから、もう示談金払ってる状態なのに、まだむしり取ろうとされてもって話ですよ!蟹工船イヤっすよ!でも蟹食べ放題なんすかね?

係)知らねーよ!

いいか、これはGnuCOBOL側の挙動ともいえるから、他の環境ではこうなるとは限らないな。

な)ぐぬ〜

係)いちいち反応すんな!

な)んじゃ諦めの境地じゃないっすか。やっぱりあの観葉植物の葉が全部落ちたらあたしも一緒に…ね状態じゃないっすか!

係)観葉植物は葉が落ちねーだろ!

だからそれが前提でどうするかを考えないといかんってことだよ!

な)あ、そゆこと

ファイルの揺れを前提にコードで守る

係)ったく。

本来であれば、パッチ処理を行いファイル自体を修正して、読み込みでエラーが生じないように整形することも考えるな。

ただ、そうなるようにコードに仕込んでおけば、リスク回避できるだろ?

な)ほほー

係)…

な)………で??

係)考えろよ。

な)ぎゃふん!

また、仕事放棄っすか!?

係)うるさい!今のコードで考えればわかるだろ!

な)ぎゃぴーん……

これが子離れ言うやつなんですね…

係)違うわ!

お前が親離れしろよ!

な)ぐぬ〜

空のレコードを数えない条件を入れる

な)…大体ここだってのはわかってんのよ。NOT AT ENDのとこでしょ、どうせ

てか、カウントしてるのここだしね

📝 COBOL カウント全体部
           OPEN INPUT OUTPUT-FILE.
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END
                       MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       ADD 1 TO COUNT-LOOPING
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.

ただ1を足し込んでるだけで、なぜか7行目にいったから、1足されてしまったんだから、ここに勝手に足さないような条件入れるのはどうだろうかしら

この際、7行目に行くのはドンマイ、丼舞として、7行目を参照したときに、データがなかったら、カウントしないでNOT AT ENDを抜けちゃうとしたらどうなのこれ?

📝 COBOL カウント部分
       NOT AT END
            IF OUTPUT-SALE-DATE NOT = SPACES
                ADD 1 TO COUNT-LOOPING
            END-IF

つまり、7行目に行っちゃうけど、最初の項目の「OUTPUT-SALE-DATE」が空(スペース)だったら、IF無しよと

そんで、空じゃなかったらカウント続ければいいじゃないのってね!

Hey うっとり!!

💻 ターミナル出力 実行結果
COUNT=07 LOW-POS=03 HIGH-POS=04
LOW-VAL=00900 HIGH-VAL=01500
MEDIAN IS 01200.0

ぎゃひー!

係長…デパートの屋上から身を乗り出して、警察に止められてきます…

係)まてまて!

死ぬなら迷惑かけずにやれ!

な)そんな慰め方あります!?

係)いい感じに沼にハマってくれるから嬉しいんだよ!

な)はぁ!?

係)改行だよ。

な)改行?

係)改行はいろいろ悪さしてくれるからな。可能性は4つほど考えられるが…

な)いやいやいやいや、4つって!4つですよ!フォーですよ!ベトナムですよ!

係)いらんこと挟むな!

複数の要因が考えられるとしても、今回は余計なレコードがあると返ってきたわけだな。
だったら、その挙動を前提に、有効なデータだけ数える処理にすればいい。

な)安易ですね

係)うるせーよ!

ヒントやったんだから考えろ!

な)あれをヒントと思っているなんて、なんて思い上がり!?人間は思い上がりすぎなんすよ!

森林伐採!環境汚染!宇宙のゴミ放置!火星をテラフォーミング!

係)(無視)

な)なんか言って!!

ぐぬ〜 … 挙動を前提ってなんだっつーのかしら

まんず、7行目ができちゃった婚ってことなのよね?

それは仕方ねーと、認知しろってことかしら?

係長も数え切れないほど認知してきたという自慢の現れかな?

係)巻き込むな!

な)でも、7行目っていうか「作られた最終行」にはデータはないってことなのよね?

だったら、> 0しちゃえばいいんじゃないの、これ!

📝 COBOL カウント全体部
           OPEN INPUT OUTPUT-FILE.
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END
                       MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT > 0
                           ADD 1 TO COUNT-LOOPING
                       END-IF
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.
💻 ターミナル出力 実行結果
COUNT=06 LOW-POS=03 HIGH-POS=04
LOW-VAL=00900 HIGH-VAL=01500
MEDIAN IS 01200.0

エイドゥリアゥーン!

係)誰だよ!

な)みてみて!ついに係長を超えましたよ!

数値判定と値判定を組み合わせる

係)ふん。

・・・

OUTPUT-AMOUNT > 0にした理由はなんだ?

な)えと…> 0だから数字じゃないとだめなんじゃないかと思って

係)考え方はいいが、それが数字かどうかの判別はしたのか?

な)へ?

数字も何も、価格のところだから数字でしょ?

係)「作られた最終行」だって自分で言ったんだろ?

だったら、そこに数字が入っている保証はあるのか?

な)へ…?

係)> 0の考え方は良いだろう。

しかし、そこに数字である保証も合わせて行わないとエラーになる可能性があるぞ。

数字判別するにはどうするんだった?もう何度もやってるだろ?

な)IS NUMERIC…?

係)つまり、IS NUMERICでの数字判定と>0の判定を同時にしろってことだ。

な)むむん

同時ってことはこう?

📝 COBOL sample.cob
           OPEN INPUT OUTPUT-FILE.
           PERFORM UNTIL EOF-FLAG = "Y"
               READ OUTPUT-FILE
                   AT END
                       MOVE "Y" TO EOF-FLAG
                   NOT AT END
                       IF OUTPUT-AMOUNT IS NUMERIC 
                          AND OUTPUT-AMOUNT > 0
                          ADD 1 TO COUNT-LOOPING
                       END-IF
               END-READ
           END-PERFORM.
           CLOSE OUTPUT-FILE.

係)それでいい。

おむすび

な)あふぅ…疲れた…

係)……で、まだ気づいてないのか?

な)へ?

係)終わってないだろ?

な)いや終わってますって!END OF FINですって!

係)ENDかFINかはっきりしろ!

な)また理不尽な…

係)それ終わらないと今日は終わらないからな!

な)へ!?

なるおは「終わる」を詠唱した

係)うるせーよ!とっとと気づけ!

な)傍若無人!?若くもないのに!?

係)そういう意味じゃないだろ!

(まだまだ続く)

係長のワンポイント

ファイル処理は「読み込めたら全部数える」ものじゃない。
本当は、読み込んだレコードが有効なデータかを確認してから使う処理だ。
よくある誤解は、NOT AT END なら正しいデータが入っていると思うことだが、空や不正なレコードが返る場合もある。
だからIS NUMERIC で数値かを確認し、さらに> 0で集計対象かを判定する。
その結果、改行や実行環境の違いで余計なレコードが現れても、件数へ混ぜずに済む。
COBOLはデータを信用して処理する言語ではなく、条件で確かめながら守る言語だ。

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

この記事を書いた人

コメント

コメントする

CAPTCHA