COBOLで同じ文字列が含まれているか検査する方法

## リストの中から入力した文字列を含むものだけを表示

フリガナ検索の機能を作りたかったときに、フォームに入力した文字列が入っているかどうかを検査する実装に苦戦したので備忘録用メモです。

## INSPECT句を使って文字列を検査する

A～Dの四つの変数を使っています。

繰り返し調べる場合はCの変数をテーブルにします。

```
INSPECT［入っているか調べたいワード変数A］
TALLYING［調べたいワードの文字数をいれる変数B］
FOR CHARACTERS BEFORE " "

INSPECT［検査するワード変数C］
TALLYING［文字列が一致した数が入る変数D］
FOR ALL［変数A］(1:［変数B］)
```

## サンプルプログラム

実際に上記を使って簡単なハンター名検索プログラムを作成。

コンソールに入力したワードがリストの中にあるか調べ、一致したものを表示します。

検査後は終了するかを聞き、もう一度検索の場合は同じ処理を繰り返します。

```
　　　******************************** 
       IDENTIFICATION DIVISION.
      ******************************** 
       
       PROGRAM-ID. YOUR-PROGRAM-NAME.
      
      ********************************
       DATA DIVISION. *>データ定義
      ******************************** 
    
       WORKING-STORAGE SECTION.
       01 HH-ARRAY OCCURS 7.
           03 CARA-NAME PIC X(25).　・・・上記例の変数C
       01 IND PIC 9(1).
       01 SEARCH-WORD PIC X(20).　・・・上記例の変数A
       01 LEN-SEARCH-WORD PIC 9(2).　・・・上記例の変数B
       01 INSPECT-RESULT PIC 9(2).　　・・・上記例の変数D
       01 END-FLAG PIC 9(1).
       01 RESULT-COUNT PIC 9(1).
       
      ********************************
       PROCEDURE DIVISION. *>処理内容
      ******************************** 
       
       SEARCH-WORD-INPUT SECTION.
           
           MOVE 1 TO IND
           MOVE 0 TO RESULT-COUNT
           MOVE "ゴン＝フリークス" TO CARA-NAME(1)
           MOVE "キルア＝ゾルディック" TO CARA-NAME(2)
           MOVE "レオリオ＝パラディナイト" TO CARA-NAME(3)
           MOVE "ジン＝フリークス" TO CARA-NAME(4)
           MOVE "ヒソカ＝モロウ" TO CARA-NAME(5)
           MOVE "イルミ＝ゾルディック" TO CARA-NAME(6)
           MOVE "アイザック＝ネテロ" TO CARA-NAME(7)
            
           DISPLAY "please input search word"
           ACCEPT SEARCH-WORD
           DISPLAY " "
           DISPLAY "***** result *****"
            
           IF SEARCH-WORD NOT = SPACE
               PERFORM UNTIL IND > 7
                   MOVE 0 TO LEN-SEARCH-WORD
                   INSPECT SEARCH-WORD
                   TALLYING LEN-SEARCH-WORD
                   FOR CHARACTERS BEFORE " "

                   MOVE 0 TO INSPECT-RESULT
                   INSPECT CARA-NAME(IND)
                   TALLYING INSPECT-RESULT
                   FOR ALL SEARCH-WORD(1:LEN-SEARCH-WORD)
               
                   IF INSPECT-RESULT > 0
                       DISPLAY CARA-NAME(IND)
                       ADD 1 TO RESULT-COUNT
                   ELSE CONTINUE
                   END-IF

                   ADD 1 TO IND

               END-PERFORM
           ELSE CONTINUE
           END-IF
            
            
           IF RESULT-COUNT > 0
               DISPLAY " "
               DISPLAY RESULT-COUNT " results found."
           ELSE
               DISPLAY "not found."
           END-IF
           
           DISPLAY "******************"
           DISPLAY " "
            
           PERFORM UNTIL END-FLAG = 2
            
               PERFORM ONE-MORE
            
               IF END-FLAG = 1 
                   GO TO SEARCH-WORD-INPUT
               END-IF
            
           END-PERFORM
           
           STOP RUN.
       EXIT.
       
       ONE-MORE SECTION.
           DISPLAY "one more? please input number => yes=1 , no=2"
           ACCEPT END-FLAG 
           
           IF END-FLAG = 2
               DISPLAY " "
               DISPLAY "see you !"
           ELSE 
               DISPLAY "***"
           END-IF
           
       EXIT.
           
       END PROGRAM YOUR-PROGRAM-NAME.
```

### 動作結果

ファミリーネームを入力

```console
please input search word
フリークス

***** result *****
ゴン＝フリークス
ジン＝フリークス

2 results found.
******************

one more? please input number => yes=1 , no=2
1
***
please input search word
ゾルディック

***** result *****
キルア＝ゾルディック
イルミ＝ゾルディック

2 results found.
******************
```

一文字だけ入力

```console
one more? please input number => yes=1 , no=2
1
***
please input search word
イ

***** result *****
レオリオ＝パラディナイト
イルミ＝ゾルディック
アイザック＝ネテロ

3 results found.
******************

one more? please input number => yes=1 , no=2
1
***
please input search word
ヒ

***** result *****
ヒソカ＝モロウ

1 results found.
******************
```

リストに存在しない名前を入力

```console
one more? please input number => yes=1 , no=2
1
***
please input search word
シルバ

***** result *****
not found.
******************

one more? please input number => yes=1 , no=2
2

see you !
```

こんな感じで入力した文字列が存在するかをテーブルを検査して検索結果を表示することができました！

## 注意点

- コンソールの文字コードの設定によってカタカナや平仮名はうまく検索できないことがあります。わたしが使ったコマンドプロンプトではchcpの文字コードの設定を932（Shift_JIS）の場合はできましたが、65001（UTF-8）の場合は使えませんでした。chcpについて詳しくは[コチラ](https://www.javadrive.jp/command/display/index5.html)。
- 上記のサンプルコードの`IF SEARCH-WORD NOT = SPACE`のように空白のままエンター押した際の分岐をしないで検査するとエラーになります。
- アルファベットの場合、大文字小文字も区別されます。同じ文字列が存在するかどうかの検査なので前方一致、後方一致のようにはなっていません。