このサイトを開設してから寄せられたCOBOLに関する質問と、私の回答を掲載しておきます。少しでも参考になれば嬉しいです。徐々に増やしていきます。
設計書に「4月10月にファイル初期化する」と書いてありまして、そこのソースを確認してみると
IF MM = 4 OR 10 OPEN OUTPUT F0001 CLOSE F0001.と、これだけです。これだけではファイルの初期が出来るとは思えないです。開いて閉じるだけで初期化できるのは意図しない事で消えてしまう危険が潜んでいそうで納得できな いんです。やはり削除するのはDELETE命令だと思うんですが…。これはこの機種だけの仕様なんでしょうか?
COBOLならではのプログラミングですね。マニュアル等には掲載されないCOBOLテクニックです。COBOLではOUTPUTでOPENした時点で、一旦ファイルを使用済みファイルに変換してくれます。つまりゼロ件のアウトファイルができあがる、即ちファイルのクリアが行なわれるのです。普通はJCL側(shell)で判定してファイルクリアのコマンドを投入するのが一般的ではありますが、こういう手法もありますよと。
DELETE命令はレコード単位の削除命令であり、ファイルのクリアには適しません。何故なら1000万件のレコードがあるファイルのクリアをするために、わざわざ1レコード毎に削除していたら丸一日掛けても処理が終わりません。
PERFORM命令の説明で、THRUという文言が出てきますがこのTHRUの意味がわからないです。
PERFORM THRU もよく見かけますね。「THRU」を直訳すれば、"通り過ぎる" になります。PERFORM AAA THRU BBB であれば、AAAからBBBまでを実行しなさいよ、という意味です。SECTION を使用しない場合に、よく利用されていますね。ちょっとサンプルでも記載してみましょうか。
PROCEDURE DIVISION. PERFORM INIT-R THRU INIT-E PERFORM READ-R THRU READ-E PERFORM LOOP-R THRU LOOP-E STOP RUN. INIT-R. OPEN IN-FILE MOVE ALL ZERO TO COUNT-AREA. INIT-E. READ-R. READ IN-FILE AT END MOVE HIGH-VALUE TO IN-REC END-READ. READ-E. LOOP-R. PERFORM UNTIL IN-REC = HIGH-VALUE ADD 1 TO IN-CNT PERFORM READ-R THRU READ-E END-PERFORM CLOSE IN-FILE DISPLAY "INPUT COUNT = " IN-CNT. LOOP-E.
どうでしょうか、わかるかな?。SECTIONで処理を分ける場合、THRUは不用になりますね。
03 KINGAKU PIC 9(4) COMP.と書かれている項目がありました。この最後についてる「COMP」の意味がわかりません。
これは「COMPUTATIONAL」という意味の予約語で実は2進数で表現されます。これをつけると数字項目はどうなるか?たとえば
working-storage section. 03 kingaku-1 pic 9(4). 03 kingaku-2 pic 9(4) comp. procedure division. move 1234 TO kingaku-1 kingku-2
とした場合を考えてみましょう。それぞれの中身を16進数で表示させてみるとはっきり違いがわかります。
kingaku-1[hex] ==> F1F2F3F4 kingaku-2[hex] ==> 04D2
ご覧のように「kingaku-1」は4バイトの項目なのですが、COMP指定があるkingaku-2の場合、使用する領域が半分の2バイトで済むわけですね。ただし中身は2進数のため人間が直接データをみてもややわかりづらいという欠点があります。補足ですが、符号つきの場合はこうなります。
working-storage section. 03 kingaku-1 pic s9(4). 03 kingaku-2 pic s9(4) comp. procedure division. move -1234 TO kingaku-1 kingku-2
kingaku-1[hex] ==> F1F2F3D4 kingaku-2[hex] ==> FB2E
2進数でマイナス表現する場合、2の補数で表現されるため中身は「FB2E」になります。どうです、もう何がなんだかわからないでしょ?だから計算領域をあまり使わないための手段、ぐらいに覚えておけばいいです。
03 KINGAKU PIC 9(4) PACKED-DECIMAL.と書かれている項目がありました。この最後についてる「PACKED-DECIMAL」の意味がわかりません。
質問3と同じような内容ですが、これは数字項目を内部10進で表現させる予約語です。これをつけると数字項目はどうなるか?早速やってみましょう。
working-storage section. 03 kingaku-1 pic s9(4). 03 kingaku-2 pic s9(4) packed-decimal. procedure division. move -1234 TO kingaku-1 kingku-2
kingaku-1[hex] ==> F1F2F3D4 kingaku-2[hex] ==> 01234D
PACKED-DECIMAL指定がある場合、中身は内部10進数になり16進数表示では、「01234D」となります。最後の「D」が符号になります。プラスは「C」マイナスは「D」で表現されます。COMPは使用する領域が半分の2バイトでしたが、PACKED-DECIMALの場合、
内部10進数の実バイト数 = [ 項目バイト数 / 2 + 0.5 ]
という計算式でバイト数を求めます。「kingaku-2 pic s9(4) packed-decimal.」の場合は…
[ 4 / 2 + 0.5 ] = 2.5 ※小数点は切り上げるため実バイト数は3バイトになる
こんな感じになり、s9(4)packed-decimailは4バイトでも2バイトでもなく実は3バイトが正解になります。この内部10進は人間が見てもすぐ数値がわかるため、実務でも頻繁に利用されます。
03 WORK-KJDT-N REDEFINES WORK-KJDT.
というのがあるんですが、このREDEFINESってなんでしょうか?
"REDEFINES"はこの文の上記にある「WORK-KJDT」という項目を再利用しますよ、という予約語です。例を挙げた方が早いかな。
01 X-REC. 03 X1 PIC X(7). 03 AAA PIC x(10). 03 BBB REDEFINES AAA. 05 CCC PIC 9(5). 05 DDD PIC X(5).
こんな感じで使用します。「AAA」という項目を「BBB」という項目(群)で再利用する手法です。「AAA」の文字列10バイトの項目を、「CCC」の数字5バイトと「DDD」の文字列5バイトという二つの項目に分解しているのがわかるでしょうか。そして…
MOVE ZERO TO CCC MOVE "ABCDE" TO DDD DISPLAY "AAA = " AAA
結果 AAA = 00000ABCDE
わかりますか?こんな感じで項目を別の項目として編集する手法です。ちなみにREDEFINESは「01レベル」での利用はできないという点に注意しましょう。
コボルでデータの長さを得る関数は存在するのでしょうか?(C言語だとSTRLENみたいな)
結論を言えばありません。COBOLは全て固定長なので、データ長=項目長になります。ここら辺がCやJava言語に比べCOBOLが発展しない理由の一因ですね。ただし、固定長項目の中身が空白以外で何バイト利用されているのか?という調査であればINSPECT命令を利用すれば得ることができます。詳しい使用例は命令語ページを参照して下さい。
情報処理試験の過去問題をといているのですがどうしても時間がかかってしまいます。早く解けるようになるには慣れるしかないのでしょうか?特に作業場所節の行数が多いと混乱します。何か良いアドバイスはありますか?
そのお気持ちはよくわかります。私も問題によっては解答するまでに時間がかかります。コツと言えるかわかりませんが、WORKING-STORAGE SECTIONは最初は見ないで無視しましょう。あくまで私の場合ですが、設問の付近しか見ません。出題者が問題を出す場所というのはある程度予測できます。
まずはざっと手続き部をみて、利用されている変数を洗い出します。問題には必要最低限の変数しかありません。多くて5,6個でしょうか。ココで初めてWORKINGをみます。洗い出した変数の桁数とサイン付き(符号付き)かどうかだけの確認です。各変数がどういう用途で使われているのかを考えれば、自ずと問題も解けるはずです。簡単に言ってますけど、やはり慣れは必要でしょうね。頑張って下さい。
DownloadしたCOBOL85で自分のマシンのプリンターに出力したい場合、どのように記述すればよいのでしょうか?
SELECT 出力ファイル名 ASSIGN TO PRINTER.
と記述して下さい。これでパソコンに接続されている標準プリンタへ印字されるはずです。
学校で習っているビットとバイトの違いすらわかりません。こんな私でも大丈夫なんでしょうか?
不安になる気持ちはわかります。これは単位の違いです。長さの単位で喩えれば、センチとメートルの違いです。ビットは一番小さいデータの単位で、バイトは時給で働く人のことです。うん、嘘。バイトはビットの上の単位です。1メートルが100センチなら、1バイトは8ビットになります。じゃあ具体例を出しましょうか。
01 w-byte1 pic 9(1) value 3.
数字1桁の項目に「3」が入っています。これを16進数で表示した場合、中身はこうなります。
w-byte1[hex] ==> F3
じゃあこれをビット(2進数)で表示した場合、中身はこうなります。
w-byte1[bin] ==> 1111 0011
つまり、プログラム上での最小単位はバイトなんですが、実際その1バイトの中身は8ビットで構成されてますよ、ということです。全然関係ないですが、昔ネオジオというゲームメーカーが「100メガショック!」というCMをやってました。実はアレ、100メガバイトじゃなくて100メガビットだったらしいですよ、という補足トリビアでした。
SORT命令はファイルソート用だと思うのですが、プログラムの内部テーブルをソートする方法はあるのでしょうか?もしサンプルがあれば教えて下さい。
内部ソートですが、COBOLの場合は手動による並び替えが一般的かと思われます。これはテクニック的なものなので、人によって方法は色々あります。じゃあ具体的にどうやるか。
WORKING-STORAGE SECTION. 01 WORK-TABLE. 02 ITEM PIC X(02) OCCURS 10. 01 WK-ITEMS PIC X(20) VALUE "02010304050604030201". 01 A PIC 9(02). 01 B PIC 9(02). 01 C PIC 9(02). 01 ITEMW PIC X(02). PROCEDURE DIVISION. * * 事前準備としてテーブルにデータを格納しておきます * MOVE WK-ITEMS TO WORK-TABLE * * 内部ソート(テーブルの並び替え) * PERFORM VARYING A FROM 1 BY 1 UNTIL A > 10 COMPUTE C = A + 1 PERFORM VARYING B FROM C BY 1 UNTIL B > 10 IF ITEM(A) < ITEM(B) CONTINUE ELSE MOVE ITEM(A) TO ITEMW MOVE ITEM(B) TO ITEM(A) MOVE ITEMW TO ITEM(B) END-IF END-PERFORM END-PERFORM 〜(以下略)〜
こんな感じでしょうか。結局やってることは本当にトロクサイです。なーんだと思われるかもしれませんね。命令文を突き詰めて考えると、他に劇的な手法があれば別ですが、命令文自体の中身って案外こんな構造なんじゃないかと思いますよ。こういう単純なロジックをひとつの命令語として定義しているだけじゃないかと。
03 KINGAKU PIC 9(05)V9.と書かれている項目がありました。この「V9」の意味がわかりません。
PICTURE句の中に記述できる「V」、これは想定小数点の位置を示しています。想定小数点とは、データとしては単なるひとつの数字項目ですが、プログラム内では小数点以下として取り扱われる領域の指定です。また最後の「9」は単純に「9(01)」の省略系です。文章で説明するより例題を出したほうが一目瞭然ですね。
DATA DIVISION. FILE SECTION. FD O-FILE. 01 O-REC. 02 O-KIN-2 PIC 9(5)V9(2). WORKING-STORAGE SECTION. 01 KIN-0 PIC 9(5). *> 数字5桁、小数なし 01 KIN-1 PIC 9(5)V9. *> 数字5桁、小数1位 01 KIN-2 PIC 9(5)V99. *> 数字5桁、小数2位 01 KIN-1-1 PIC 9(5)V9(1). *> KIN-1 と同じ意味 01 KIN-2-1 PIC 9(5)V9(2). *> KIN-2 と同じ意味 PROCEDURE DIVISION. MOVE 12345.12 TO KIN-0 KIN-1 KIN-2 DISPLAY "KIN-0=" KIN-0 " | KIN-1=" KIN-1 " | KIN-2=" KIN-2 OPEN O-FILE WRITE O-REC FROM KIN-2 CLOSE O-FILE STOP RUN結果は以下の通り
KIN-0=12345 | KIN-1=12345.1 | KIN-2=12345.12
このようにプログラム内で小数点以下の数字を利用するためには、必ず「V」をつけて小数点以下の桁数を指定しなければなりませんよ、ということです。 また実際に小数点をつけた状態でデータを出力すると結果はどうなったでしょうか?
O-RECの中身
1234512
上記の結果からもわかるように、データ上では小数点の有無は無視され、ただの数字7バイトとして扱われます。小数点以下を扱うときには注意してください。