【COBOL】IF文完全ガイド|比較演算子・88レベル条件名・AND/OR優先順位・クラス条件・実践パターン

COBOLのIF文は、条件によって処理を分岐させる最も基本的な命令です。一見シンプルですが、比較演算子の英語表記・88レベル条件名・AND/ORの優先順位・クラス条件など、COBOLならではの仕様が多くあります。

この記事では基本構文から始め、COBOLのIF文で使えるすべての条件の種類、論理演算子の評価順序、ネストを整理する実践的な書き方まで体系的に解説します。業務バリデーション・ファイルSTATUS判定・範囲チェックの実践コードも合わせて紹介します。

この記事でわかること

  • IF文の基本構文とEND-IFの使い方
  • 比較演算子の記号表記と英語表記の対応
  • 88レベル条件名でIF文を読みやすくする方法
  • AND・OR・NOTの評価順序と括弧による制御
  • クラス条件(NUMERIC/ALPHABETIC)と符号条件(POSITIVE/NEGATIVE/ZERO)
  • ネストIF文の整理方法とEVALUATEとの使い分け
  • 業務バリデーション・ファイルSTATUS判定の実践パターン
スポンサーリンク

IF文の基本構文

COBOLのIF文の基本形は次のとおりです。END-IFで明示的に終了させる書き方が現代COBOLの標準です。

IF文の基本構文
IF 条件式
    処理1(条件が真のとき)
[ELSE
    処理2(条件が偽のとき)]
END-IF.

END-IFとピリオド終端の違い

古いCOBOLコードではEND-IFを書かず、ピリオド(.)で文を終わらせる書き方が使われていました。しかし現代のCOBOLではEND-IFを使うことが強く推奨されます。

旧スタイル(ピリオド終端)vs 現代スタイル(END-IF)
*--- 旧スタイル(ピリオド終端)---
*> ピリオドはIF文だけでなくそれ以降の全文を終わらせるため
*> 意図しない範囲でIF文が終了するバグが発生しやすい
    IF WS-AMOUNT > 0
        PERFORM CALC-TAX
        MOVE 'Y' TO WS-VALID-FLG.   *> ここで文ブロック全体が終了

*--- 現代スタイル(END-IF必須)---
*> 可読性が高く、ネストしても範囲が明確
    IF WS-AMOUNT > 0
        PERFORM CALC-TAX
        MOVE 'Y' TO WS-VALID-FLG
    END-IF.
注意: ピリオドの落とし穴
旧スタイルのコードを保守するとき、ピリオドの位置を誤って移動するだけで条件分岐の範囲が変わってしまいます。保守案件でも新規追加部分はEND-IFを使い、ピリオドは段落末尾の1か所だけに限定するのが安全です。

比較演算子の種類

COBOLの比較演算子には記号表記と英語表記の2種類があります。どちらを使っても同じ意味ですが、業務コードでは英語表記が読みやすい場合が多くあります。

記号 英語表記 意味 使用例
= IS EQUAL TO 等しい WS-CODE = ’01’ または WS-CODE IS EQUAL TO ’01’
> IS GREATER THAN 大きい WS-AGE > 18
< IS LESS THAN 小さい WS-PRICE < 1000
>= IS GREATER THAN OR EQUAL TO 以上 WS-SCORE >= 60
<= IS LESS THAN OR EQUAL TO 以下 WS-LEVEL <= 5
NOT = IS NOT EQUAL TO 等しくない WS-STATUS NOT = ‘OK’
NOT > IS NOT GREATER THAN 大きくない(以下) WS-AMT NOT > 9999
NOT < IS NOT LESS THAN 小さくない(以上) WS-CNT NOT < 1
比較演算子の使用例
WORKING-STORAGE SECTION.
01 WS-SCORE        PIC 9(3).
01 WS-GRADE        PIC X(1).

PROCEDURE DIVISION.
    EVALUATE TRUE
        WHEN WS-SCORE >= 90
            MOVE 'A' TO WS-GRADE
        WHEN WS-SCORE >= 70
            MOVE 'B' TO WS-GRADE
        WHEN WS-SCORE >= 50
            MOVE 'C' TO WS-GRADE
        WHEN OTHER
            MOVE 'F' TO WS-GRADE
    END-EVALUATE.

*> IF文で同じ処理を書く場合
    IF WS-SCORE IS GREATER THAN OR EQUAL TO 90
        MOVE 'A' TO WS-GRADE
    ELSE
        IF WS-SCORE >= 70
            MOVE 'B' TO WS-GRADE
        ELSE
            IF WS-SCORE >= 50
                MOVE 'C' TO WS-GRADE
            ELSE
                MOVE 'F' TO WS-GRADE
            END-IF
        END-IF
    END-IF.
多分岐にはEVALUATEが最適
3段階以上の段階的な条件分岐(スコアのABCF判定など)はIF文をネストするよりもEVALUATE文の方が可読性が大幅に高くなります。IF文は2分岐か、単純な条件チェックに向いています。

88レベル条件名でIF文を読みやすくする

88レベルは変数の特定の値に「名前」を付ける機能です。IF文と組み合わせると、コードが英語の文章に近い可読性になります。業務ロジックが複雑なCOBOLプログラムでは積極的に使うべき機能です。

88レベル条件名の定義と使い方
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-GENDER           PIC X(1).
   88 MALE             VALUE 'M'.
   88 FEMALE           VALUE 'F'.

01 WS-ORDER-STATUS     PIC X(2).
   88 STATUS-PENDING   VALUE '01'.
   88 STATUS-APPROVED  VALUE '02'.
   88 STATUS-SHIPPED   VALUE '03'.
   88 STATUS-DELIVERED VALUE '04'.
   88 STATUS-CANCELLED VALUE '09'.
   88 STATUS-ACTIVE    VALUE '01' '02' '03'.  *> 複数値をまとめて定義

01 WS-HTTP-CODE        PIC 9(3).
   88 HTTP-SUCCESS     VALUE 200 THRU 299.    *> 範囲で定義
   88 HTTP-CLIENT-ERR  VALUE 400 THRU 499.
   88 HTTP-SERVER-ERR  VALUE 500 THRU 599.

PROCEDURE DIVISION.
    *> 88レベルなし(可読性が低い)
    IF WS-ORDER-STATUS = '01' OR WS-ORDER-STATUS = '02'
        OR WS-ORDER-STATUS = '03'
        DISPLAY '処理中の注文です'
    END-IF.

    *> 88レベルあり(意図が一目でわかる)
    IF STATUS-ACTIVE
        DISPLAY '処理中の注文です'
    END-IF.

    IF HTTP-SUCCESS
        DISPLAY 'APIコール成功'
    ELSE IF HTTP-SERVER-ERR
        DISPLAY 'サーバーエラーが発生しました'
    END-IF.
88レベルの値をSETで変更する
*> 88レベルはIF文で「読む」だけでなく、SET文で「書く」こともできる
PROCEDURE DIVISION.
    *> STATUS-APPROVEDをTRUEにセット = WS-ORDER-STATUSに'02'を代入
    SET STATUS-APPROVED TO TRUE.

    *> 確認
    IF STATUS-APPROVED
        DISPLAY '注文は承認済みです'
    END-IF.

    *> FALSE指定はCOBOLではサポートされていないため、
    *> 別の値をSETするか直接MOVEする
    SET STATUS-CANCELLED TO TRUE.    *> '09'をセット
88レベル設計のコツ

  • ステータスコードや区分値を持つ項目には必ず88レベルを定義する
  • 複数の値をまとめる場合はVALUE A B C または VALUE A THRU B で定義する
  • 88レベルの名前は「形容詞的・状態的」な名前にする(IS-VALID、ORDER-ACTIVE等)
  • COPYライブラリに88レベル定義を集約すると複数プログラム間で一貫性を保てる

AND・OR・NOTの評価順序と括弧

複数の条件を組み合わせるときはAND・OR・NOTを使います。COBOLの評価順序はNOT → AND → ORの順です。括弧で明示的にグループ化すると意図が伝わりやすく、バグも防げます。

演算子 優先順位 意味
NOT 1(最高) 条件を反転する NOT WS-FLAG = ‘Y’
AND 2 両方の条件が真のとき真 WS-AGE >= 18 AND WS-COUNTRY = ‘JP’
OR 3(最低) どちらか一方が真のとき真 WS-TYPE = ‘A’ OR WS-TYPE = ‘B’
評価順序の注意点と括弧の使い方
WORKING-STORAGE SECTION.
01 WS-AGE          PIC 9(3).
01 WS-COUNTRY      PIC X(2).
01 WS-MEMBER-TYPE  PIC X(1).

PROCEDURE DIVISION.
*> --- 意図しない評価の例 ---
*> 「日本在住18歳以上」OR「Aタイプ会員」と読みたいが…
    IF WS-COUNTRY = 'JP' AND WS-AGE >= 18 OR WS-MEMBER-TYPE = 'A'

*> ANDがORより優先されるので、実際の評価は:
*> (WS-COUNTRY = 'JP' AND WS-AGE >= 18) OR (WS-MEMBER-TYPE = 'A')
*> → Aタイプ会員なら国籍・年齢問わずTRUEになってしまう

*> --- 括弧で意図を明確にする ---
    IF (WS-COUNTRY = 'JP' OR WS-MEMBER-TYPE = 'A')
       AND WS-AGE >= 18
*> → 「JPまたはAタイプ、かつ18歳以上」という意図が正確に表現される
    END-IF.

*> --- NOTの使い方 ---
    IF NOT (WS-AGE < 18)           *> WS-AGE >= 18 と同じ
        CONTINUE
    END-IF.

    IF NOT (WS-COUNTRY = 'JP' OR WS-COUNTRY = 'US')
        DISPLAY '対象外の国です'   *> JPでもUSでもない場合
    END-IF.

短絡評価(Short-circuit)に関する注意

COBOLは短絡評価(最初の条件だけで結果が決まる場合に2番目以降を評価しない)を保証しないコンパイラが多いです。AND条件の最初にNULL/空白チェックを置いても、2番目の条件が必ず評価される場合があるため、副作用のある評価式は避けましょう。

条件の種類:クラス条件・符号条件

COBOLには通常の比較以外にも、データの種別数値の符号を調べる専用の条件があります。入力バリデーションで特に役立ちます。

クラス条件

変数の内容が特定の文字クラスに属するかを調べます。

条件 意味
NUMERIC 0〜9のみで構成されている(符号付き数値も可)
NOT NUMERIC 数字以外の文字を含む
ALPHABETIC A〜Z・a〜zおよびスペースのみで構成されている
ALPHABETIC-UPPER A〜Zおよびスペースのみ
ALPHABETIC-LOWER a〜zおよびスペースのみ
NOT ALPHABETIC 英字以外を含む
クラス条件の使用例
WORKING-STORAGE SECTION.
01 WS-INPUT        PIC X(10).
01 WS-CUST-ID      PIC X(8).
01 WS-ERR-MSG      PIC X(40).

PROCEDURE DIVISION.
    *> 入力値が数値かどうかを確認
    IF WS-INPUT IS NUMERIC
        MOVE FUNCTION NUMVAL(WS-INPUT) TO WS-AMOUNT
    ELSE
        MOVE '入力値が数値ではありません' TO WS-ERR-MSG
        PERFORM ERROR-HANDLER
    END-IF.

    *> 顧客IDが英大文字のみかを確認
    IF WS-CUST-ID IS NOT ALPHABETIC-UPPER
        MOVE 'IDに使用できない文字が含まれています' TO WS-ERR-MSG
        PERFORM ERROR-HANDLER
    END-IF.

符号条件

数値型変数の符号(正・負・ゼロ)を調べます。

条件 意味
POSITIVE 0より大きい(正の数)
NEGATIVE 0より小さい(負の数)
ZERO / ZEROS / ZEROES 値が0である
NOT POSITIVE 0以下(0または負の数)
NOT NEGATIVE 0以上(0または正の数)
NOT ZERO 0でない
符号条件の使用例
WORKING-STORAGE SECTION.
01 WS-BALANCE      PIC S9(9)V99.   *> 符号付き残高
01 WS-DIFF         PIC S9(9)V99.   *> 差額(負になりうる)

PROCEDURE DIVISION.
    *> 残高チェック
    IF WS-BALANCE IS NEGATIVE
        DISPLAY '残高が不足しています: ' WS-BALANCE
        PERFORM OVERDRAFT-PROCESS
    ELSE IF WS-BALANCE IS ZERO
        DISPLAY '残高はゼロです'
    ELSE
        DISPLAY '残高: ' WS-BALANCE
    END-IF.

    *> 差額の符号チェック
    COMPUTE WS-DIFF = WS-ACTUAL-AMT - WS-BUDGET-AMT
    IF WS-DIFF IS POSITIVE
        DISPLAY '予算超過: ' WS-DIFF
    ELSE IF WS-DIFF IS NEGATIVE
        DISPLAY '予算内: 残り ' FUNCTION ABS(WS-DIFF)
    ELSE
        DISPLAY '予算ちょうど'
    END-IF.

ネストIF文の書き方と整理のコツ

IF文の中にさらにIF文を書くことをネストといいます。ネストが深くなるとコードが読みにくくなるため、構造を整理する方法を知っておくことが重要です。

ELSE IFで縦に並べる

条件が排他的(どれか1つが成立する)な場合は、ELSE IFを使って縦に並べるとネストが深くなりません。

ELSE IFによるフラットな条件分岐
*> NG: ネストが深い書き方
    IF WS-REGION = 'NORTH'
        PERFORM NORTH-PROC
    ELSE
        IF WS-REGION = 'SOUTH'
            PERFORM SOUTH-PROC
        ELSE
            IF WS-REGION = 'EAST'
                PERFORM EAST-PROC
            ELSE
                PERFORM DEFAULT-PROC
            END-IF
        END-IF
    END-IF.

*> OK: ELSE IFでフラットにする
    IF WS-REGION = 'NORTH'
        PERFORM NORTH-PROC
    ELSE IF WS-REGION = 'SOUTH'
        PERFORM SOUTH-PROC
    ELSE IF WS-REGION = 'EAST'
        PERFORM EAST-PROC
    ELSE
        PERFORM DEFAULT-PROC
    END-IF.

条件を逆転させて早期リターンする

エラーチェックの条件を最初に処理して早めに抜けることで、主処理をネストなしに書けます。

ガード節パターン(早期GOBACK)
PROCEDURE DIVISION.
    *> 入力値チェックを先に行い、NGならすぐ終了
    IF WS-CUST-ID = SPACES
        MOVE 4 TO RETURN-CODE
        DISPLAY '顧客IDが未入力です'
        GOBACK
    END-IF.

    IF WS-AMOUNT IS NOT NUMERIC
        MOVE 8 TO RETURN-CODE
        DISPLAY '金額に数値以外が含まれています'
        GOBACK
    END-IF.

    IF WS-AMOUNT <= ZERO
        MOVE 8 TO RETURN-CODE
        DISPLAY '金額は1以上を入力してください'
        GOBACK
    END-IF.

    *> チェックをすべてパスした場合の主処理(ネストなし)
    PERFORM MAIN-PROCESS.
    MOVE 0 TO RETURN-CODE.
    GOBACK.

ネストが深いときはPERFORMに切り出す

複雑な条件ブロックは段落(パラグラフ)に切り出してPERFORMで呼ぶと、各IF文がシンプルになります。

段落に切り出してPERFOMで呼ぶ
PROCEDURE DIVISION.
MAIN-LOGIC.
    *> 各チェックを段落に切り出してすっきり
    PERFORM VALIDATE-INPUT
    IF WS-VALID-FLG = 'Y'
        PERFORM CALC-AMOUNT
        PERFORM OUTPUT-RESULT
    ELSE
        PERFORM OUTPUT-ERROR
    END-IF
    STOP RUN.

VALIDATE-INPUT.
    MOVE 'Y' TO WS-VALID-FLG
    IF WS-CUST-ID = SPACES
        MOVE 'N' TO WS-VALID-FLG
        MOVE 'E001' TO WS-ERR-CODE
    END-IF
    IF WS-VALID-FLG = 'Y' AND WS-AMOUNT <= ZERO
        MOVE 'N' TO WS-VALID-FLG
        MOVE 'E002' TO WS-ERR-CODE
    END-IF.

CALC-AMOUNT.
    COMPUTE WS-TAX    = WS-AMOUNT * .10
    COMPUTE WS-TOTAL  = WS-AMOUNT + WS-TAX.

OUTPUT-RESULT.
    DISPLAY '税込合計: ' WS-TOTAL.

OUTPUT-ERROR.
    DISPLAY 'エラー: ' WS-ERR-CODE.

IF文とEVALUATE文の使い分け

COBOLでの条件分岐はIF文かEVALUATE文(完全ガイドはこちら)のどちらかを選択できます。用途に応じた使い分けの目安を示します。

ユースケース 推奨 IF文 EVALUATE文
2分岐(YES/NO) IF-ELSE
3段階以上の排他的条件 EVALUATE △(ネストが深くなる)
範囲条件(THRU) EVALUATE △(書きにくい) ○(WHEN THRU)
複数の主語を同時判定 EVALUATE ALSO ✕(不可)
88レベル条件名を活用 IF(EVALUATE共に可)
エラーチェック・早期リターン IF(ガード節)
真偽値フラグ1つのチェック IF

実践パターン4選

入力バリデーション(複数条件の組み合わせ)

業務入力値の複合チェック
WORKING-STORAGE SECTION.
01 WS-VALID-FLG    PIC X(1) VALUE 'Y'.
   88 INPUT-VALID  VALUE 'Y'.
   88 INPUT-INVALID VALUE 'N'.
01 WS-ERR-CODE     PIC X(4).
01 WS-CUST-ID      PIC X(8).
01 WS-AMOUNT       PIC X(10).
01 WS-AMOUNT-NUM   PIC 9(9)V99.
01 WS-TRANS-TYPE   PIC X(2).
   88 TYPE-DEPOSIT    VALUE 'D'.
   88 TYPE-WITHDRAWAL VALUE 'W'.
   88 TYPE-TRANSFER   VALUE 'T'.

VALIDATE-INPUT.
    SET INPUT-VALID TO TRUE

    *> 顧客ID必須チェック
    IF WS-CUST-ID = SPACES
        SET INPUT-INVALID TO TRUE
        MOVE 'V001' TO WS-ERR-CODE
        GO TO VALIDATE-END
    END-IF

    *> 顧客IDフォーマットチェック(英大文字8桁)
    IF WS-CUST-ID IS NOT ALPHABETIC-UPPER
        SET INPUT-INVALID TO TRUE
        MOVE 'V002' TO WS-ERR-CODE
        GO TO VALIDATE-END
    END-IF

    *> 金額数値チェック
    IF WS-AMOUNT IS NOT NUMERIC
        SET INPUT-INVALID TO TRUE
        MOVE 'V003' TO WS-ERR-CODE
        GO TO VALIDATE-END
    END-IF
    MOVE FUNCTION NUMVAL(WS-AMOUNT) TO WS-AMOUNT-NUM

    *> 取引タイプに応じた金額チェック
    IF TYPE-WITHDRAWAL OR TYPE-TRANSFER
        IF WS-AMOUNT-NUM <= ZERO OR WS-AMOUNT-NUM > 1000000
            SET INPUT-INVALID TO TRUE
            MOVE 'V004' TO WS-ERR-CODE
            GO TO VALIDATE-END
        END-IF
    END-IF

    VALIDATE-END.
    EXIT.

ファイルSTATUSコードの判定

ファイル操作後のSTATUSコードを88レベルで定義し、IF文でハンドリングするパターンです。

ファイルSTATUSの88レベル定義と判定
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-FILE-STATUS   PIC X(2).
   88 FILE-OK       VALUE '00'.
   88 FILE-EOF      VALUE '10'.
   88 FILE-NOT-FOUND VALUE '35'.
   88 FILE-LOCKED   VALUE '99'.
   88 FILE-ERROR    VALUE '04' '07' '30' '34'
                          '37' '38' '39' '41'
                          '42' '43' '44' '46'
                          '47' '48' '49'.

PROCEDURE DIVISION.
    OPEN INPUT MASTER-FILE
    IF NOT FILE-OK
        IF FILE-NOT-FOUND
            DISPLAY 'ファイルが見つかりません'
            MOVE 8 TO RETURN-CODE
        ELSE
            DISPLAY 'ファイルオープンエラー: ' WS-FILE-STATUS
            MOVE 12 TO RETURN-CODE
        END-IF
        GOBACK
    END-IF

    PERFORM UNTIL FILE-EOF
        READ MASTER-FILE
            AT END
                CONTINUE
            NOT AT END
                PERFORM PROCESS-RECORD
        END-READ
    END-PERFORM

    CLOSE MASTER-FILE
    IF NOT FILE-OK
        DISPLAY 'クローズエラー: ' WS-FILE-STATUS
    END-IF.

数値範囲の判定(THRU / ANDを使った範囲チェック)

年齢区分・金額ランク判定
WORKING-STORAGE SECTION.
01 WS-AGE          PIC 9(3).
01 WS-AGE-GROUP    PIC X(10).
01 WS-AMOUNT       PIC 9(9)V99.
01 WS-DISCOUNT-RATE PIC V9(2).

PROCEDURE DIVISION.
    *> 年齢区分(ANDを使った範囲チェック)
    IF WS-AGE >= 0 AND WS-AGE <= 12
        MOVE '子ども' TO WS-AGE-GROUP
    ELSE IF WS-AGE >= 13 AND WS-AGE <= 17
        MOVE '中高生' TO WS-AGE-GROUP
    ELSE IF WS-AGE >= 18 AND WS-AGE <= 64
        MOVE '一般'   TO WS-AGE-GROUP
    ELSE IF WS-AGE >= 65
        MOVE 'シニア' TO WS-AGE-GROUP
    ELSE
        MOVE '不明'   TO WS-AGE-GROUP
    END-IF.

    *> 金額に応じた割引率
    IF WS-AMOUNT >= 100000
        MOVE .15 TO WS-DISCOUNT-RATE    *> 15%割引
    ELSE IF WS-AMOUNT >= 50000
        MOVE .10 TO WS-DISCOUNT-RATE    *> 10%割引
    ELSE IF WS-AMOUNT >= 10000
        MOVE .05 TO WS-DISCOUNT-RATE    *> 5%割引
    ELSE
        MOVE .00 TO WS-DISCOUNT-RATE    *> 割引なし
    END-IF.

日付バリデーション(クラス条件×範囲チェック)

入力日付の形式と範囲チェック
WORKING-STORAGE SECTION.
01 WS-DATE-INPUT   PIC X(8).         *> YYYYMMDD形式
01 WS-YEAR         PIC 9(4).
01 WS-MONTH        PIC 9(2).
01 WS-DAY          PIC 9(2).
01 WS-DATE-VALID   PIC X(1).
   88 DATE-OK      VALUE 'Y'.
   88 DATE-NG      VALUE 'N'.

CHECK-DATE.
    SET DATE-OK TO TRUE

    *> 8桁数値チェック
    IF WS-DATE-INPUT IS NOT NUMERIC
        SET DATE-NG TO TRUE
        MOVE 'E001' TO WS-ERR-CODE
        GO TO CHECK-DATE-END
    END-IF

    MOVE WS-DATE-INPUT(1:4) TO WS-YEAR
    MOVE WS-DATE-INPUT(5:2) TO WS-MONTH
    MOVE WS-DATE-INPUT(7:2) TO WS-DAY

    *> 年チェック
    IF WS-YEAR < 2000 OR WS-YEAR > 2099
        SET DATE-NG TO TRUE
        MOVE 'E002' TO WS-ERR-CODE
        GO TO CHECK-DATE-END
    END-IF

    *> 月チェック
    IF WS-MONTH < 1 OR WS-MONTH > 12
        SET DATE-NG TO TRUE
        MOVE 'E003' TO WS-ERR-CODE
        GO TO CHECK-DATE-END
    END-IF

    *> 日チェック(簡易版: 28〜31日は月によって要別途チェック)
    IF WS-DAY < 1 OR WS-DAY > 31
        SET DATE-NG TO TRUE
        MOVE 'E004' TO WS-ERR-CODE
    END-IF

    CHECK-DATE-END.
    EXIT.

よくある落とし穴と対策

落とし穴 問題 対策
END-IFの書き忘れ 条件ブロックの終端が不明瞭になり、ネストが誤って閉じてバグになる 必ずEND-IFで閉じる。ピリオドは段落末の1か所のみ
AND/OR優先順位の誤解 ANDがORより優先されるため「A AND B OR C」は「(A AND B) OR C」と評価される 括弧で意図を明示する。3つ以上の条件が混在する場合は必ず括弧を使う
スペースパディングの罠 PIC X(10) VALUE ‘YES’ は実際には’YES ‘(後ろにスペース7文字)で格納されている。’YES’との比較はTRUEになるが、大小比較ではスペースが影響する場合がある 文字列の比較にはDELIMITED BY SPACEやFUNCTION TRIMを使って有効部分だけを比較する
NOT ANDの誤用 NOT WS-A = 1 AND WS-B = 2 は NOT(WS-A=1) AND (WS-B=2) と評価される。全体の否定なら括弧が必要 NOT (WS-A = 1 AND WS-B = 2) と括弧で囲む
NUMERIC条件の使いすぎ PIC 9の変数はNUMERIC判定を経ずとも常に数値のはずだが、外部入力を受けたPIC X変数の検証には必須 NUMERIC条件はユーザー入力や外部ファイルからの値のバリデーションにのみ使う

よくある質問

QIF文とEVALUATE文のどちらを使うべきですか?
A条件が2つに分岐するだけならIF-ELSE、3つ以上に分岐するならEVALUATEを推奨します。EVALUATE文はWHEN THRUで範囲指定もでき、多分岐が格段に読みやすくなります。一方でエラーチェックの早期リターン(ガード節)はIF文の方が自然です。
QCOBOLのIF文でTHENは必須ですか?
ATHENは省略可能です。IF 条件 THEN 処理IF 条件 処理は同じ意味です。ただし英語に近い読み方ができるため、可読性を重視する場合はTHENを書く方が好まれることがあります。プロジェクトの規約に合わせましょう。
Q88レベルのFALSEへのSET(SET 条件名 TO FALSE)はできますか?
ACOBOL 85規格以降では88レベルにFALSE VALUE句を定義することでSET … TO FALSEが使えます。88 IS-VALID VALUE 'Y' FALSE VALUE 'N'.のように定義すると、SET IS-VALID TO FALSEMOVE 'N' TO WS-VALID-FLGと同じ効果を持ちます。ただしFALSE VALUEに対応していないコンパイラもあるため、使用前に確認が必要です。
QIF文の中でGO TOを使ってもよいですか?
A構造化プログラミングの観点ではGO TOは推奨されませんが、ガード節(エラーチェック後に段落の末尾へ飛ぶ)での使用は許容されるケースが多いです。バリデーション段落の末尾にVALIDATE-END. EXIT.を置き、各エラーチェックからGO TO VALIDATE-ENDで飛ばすパターンは実務でよく見られます。
QCOBOLのIF文で文字列の大小比較をするとき注意することはありますか?
ACOBOLの文字列比較はEBCDICまたはASCIIの文字コード順で行われます。日本語文字(全角)の大小比較は文字コード系に依存するため注意が必要です。また、PIC X定義の変数は後ろにスペースが埋まるため、長さの異なる文字列を比較するときはFUNCTION TRIMで末尾スペースを除去してから比較することをお勧めします。

まとめ

COBOLのIF文まわりのポイントを整理します。

ポイント 説明
END-IF必須 ピリオド終端ではなくEND-IFでIF文を閉じる。ネストが深くても範囲が明確になる
88レベル条件名 区分値・ステータスコードには88レベルを定義し、IFの条件を自然言語に近い形にする
AND/ORの優先順位 NOT→AND→ORの順。3条件以上が混在する場合は括弧で明示する
クラス条件 NUMERIC/ALPHABETICで入力値の種別チェックができる。外部入力のバリデーションに必須
符号条件 POSITIVE/NEGATIVE/ZEROで符号付き数値の状態を直感的にチェックできる
ガード節 エラーチェックを先に行い早期GOBACKする設計で、主処理のネストをフラットにする
多分岐はEVALUATE 3段階以上の排他的条件分岐はEVALUATEの方が可読性が高い

88レベルとガード節を組み合わせるだけで、COBOLの条件分岐コードは大幅に読みやすくなります。まず既存コードの区分値を88レベルに置き換えることから始めてみましょう。

多分岐条件の実装にはEVALUATE文の完全ガイドを、データの転送についてはMOVE文の完全ガイドを合わせてご参照ください。初期化処理はINITIALIZE文も活用できます。