🧩今日の学び
・SEARCHは「構造」を探す命令ではなく、中身が入った配列を先頭から順に確認する処理である
・OCCURSは箱を作るだけ、MOVEで中身を入れなければ係長ですらAT ENDに直行する
・SEARCHが動かないときはロジックより先に「データ入ってる?」を疑え
係長)ここまでぐるぐるやってしまったからな、ちょっと最後まで読んで、結果言ってみろ。
なるお)寄り道しすぎて、もう覚えてないっすよ⋯。
係)いいから、読めっての!
な)むー、相変わらず問答無用なんだから⋯
01 ITEM-TABLE.
05 ITEM-REC OCCURS 5 TIMES
INDEXED BY IDX.
10 ITEM-ID PIC X(3).
10 ITEM-NAME PIC X(10).
01 TARGET-ID PIC X(3) VALUE "003".
SET IDX TO 1
SEARCH ITEM-REC
AT END
DISPLAY "見つかりません"
WHEN ITEM-ID(IDX) = TARGET-ID
DISPLAY "見つけた: " ITEM-NAME(IDX)
END-SEARCH
な)んだば、このコードの結果は、TARGET IDが003で、ITEM-IDの3つ目に矢印(IDX)が来たときに一致となって…?
…… って、あれ? 係長?ITEM-IDの中身って入れました?
SEARCHは「箱」を探してくれる魔法ではない
係)…ん?
な)だってOCCURS 5 TIMES で「箱」は作ったわけじゃないすか?
でも、その箱の中身って空じゃないですか?
いくらIDXという矢印があっても、その矢印の指した先が空なら、一生一致しないですよね?
これ、最終的にAT ENDに飛んで「見つかりません」ってなりません?
係)んが!?
な)係長、もしかして… データ入れるの忘れてました? やっちまいました?
係)こ、これはお前の理解力を問うたんであってだな!
これはその、なんだ …… うぅ、すまん、データ入れるのを忘れてた…。
な)えー! 完璧超人の係長が! アンドロイド係長が!Windows Phoneな係長が!?
謝りました!?謝っちゃいました!? 明日はパイン大福が降るんじゃないすか?
係)うるさいな! なんだよパイン大福って!誰にでもミスはあるだろ!
… ま、まぁ、今のを聞いていると、きちんと「定義とデータ」の違いは理解しているようだな!
「最終的に」という言葉から、未定義=中身が空=AT END という流れが見えている証拠だ。
SEARCHが正しく動いた瞬間:データが入って初めて意味を持つ
係)でだ!こうやって「中身」を入れたらどうだ?
PROCEDURE DIVISION.
MOVE "003" TO ITEM-ID(3).
MOVE "ORANGE" TO ITEM-NAME(3).
SET IDX TO 1.
SEARCH ITEM-REC
AT END
DISPLAY "見つかりません"
WHEN ITEM-ID(IDX) = TARGET-ID
DISPLAY "見つけた: " ITEM-NAME(IDX)
END-SEARCH.
STOP RUN.
な)おー!MOVE が入った!MOVE が入った! 今日はビフテキですね!
係)お前、さっきからバカにしてるだろ…。
な)むふー!
えっと、これで3番目の箱に「003」と「ORANGE」が入りましたと。
で、SEARCHが回って、3番目でITEM-ID(IDX) が”003″と一致するから…DISPLAYに進んで、「見つけた: ORANGE」ってなるわけっすね!
係)そうだな、正解だ。
箱を作る(定義)のと、中身を入れる(転送)のは別作業だということだ。
ちなみに、今データを入れるのに使った ITEM-ID(3) はSUBSCRIPTでのピンポイントの指定だ。SEARCHで使うINDEXとは別物だから混同するなよ。
おむすび
な)いやー、それにしても係長の珍しいミスでしたね!
係)なんでそんな嬉しそうなんだよ!
な)一生忘れませんよ! 「んがっ!」って言ってたこととか! ぷふふー
係)だから、なんでこういう余計なことは忘れないんだよ!すぐ忘れろよ!
そもそもWindows Phoneってなんだよ!おれはAndroidだ!
な)あ!やっぱり係長、ヒューマノイドだったんすね!
係)ちがーう!!
係長のワンポイント
SEARCH は「箱」を探す命令じゃない。
中身が入った箱を、先頭から順に確認する処理だ。OCCURSは構造を作るだけで、データは一切入れてくれない。
定義と転送を混同すると、正しいコードでも必ずAT ENDに行く。SEARCHが動かないときは、まず中身が入っているかを疑え。

コメント