COBOL로 탕시어머니~ 2바이트 문자판정법~

12320 단어 cobol탕파

개시하다


@Nemesis선생님의 "Java로 찌개 시어머니 해보세요."이 화제인데 유행하는 틈을 타서 하고 싶어요.
아직 쓰이지 않은 언어라 기존에 사용했던 코볼에서 해보기로 했다.

필요한 처리에 해당하는 COBOL 문


탕시어머니의 처리 절차는 다음과 같은 네 가지 공정이다.
① 콘솔에 정의된 정보 출력
② 콘솔에 입력한 이름 받기
③ 몇 글자를 무작위로 결정
④ 정해진 정보에 텍스트를 포함하여 출력
각 처리에 대한 COBOL 문은 다음과 같습니다.
  • 콘솔 출력DISPLAY 変数.
  • 콘솔 입력ACCEPT 変数 FROM CONSOLE.
  • 랜덤FUNCTION RANDOM().
  • 값의 대입MOVE 1 TO 変数.
  • 부분 문자열 가져오기文字型変数(開始Index:取得バイト数)- 변수 선언01 変数 PIC X(40).- 주석 출력7バイト目に*を付けた行
  • 코드(하나)


    길어서 접고 있어요.
           IDENTIFICATION DIVISION.
           PROGRAM-ID. coba-ba.
           AUTHOR. Keita INAGAKI.
           ENVIRONMENT DIVISION.
           CONFIGURATION SECTION.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
          *
           01  IN-NAME         PIC X(40).
           01  RAND-VAL        PIC V9(10).
           01  INPUT-SIZE      PIC 9(5).
           01  TMP-IDX         PIC 9(5).
           01  RESULT-INDEX    PIC 9(5).
           01  SEED-VAL        PIC 9(5).
          * 乱数のシードに渡せるのは0~32767のため、分秒4桁を渡す
           01  DATE-NOW.
               03  DATE-NOW-YY        PIC X(04).
               03  DATE-NOW-MM        PIC X(02).
               03  DATE-NOW-DD        PIC X(02).
               03  DATE-NOW-HH        PIC X(02).
               03  DATE-NOW-FFSS      PIC X(04).
          *
          ******************************************************************
          *  PROCEDURE DIVISION
          ******************************************************************
           PROCEDURE DIVISION.
           CNTL SECTION.
          *    メッセージ出力
               DISPLAY "契約書だよ。そこに名前を書きな。".
          *    コンソール入力を受け取る
               ACCEPT IN-NAME      FROM CONSOLE.
          *    入力文字長の取得
               PERFORM GET-INPUT-SIZE.
               DISPLAY "フン。"
                       IN-NAME(1:INPUT-SIZE)
                       "というのかい。贅沢な名"
                       "だねぇ。".
          *    文字を奪う
               PERFORM TAKE-AWAY-STRING.
          *     DISPLAY RESULT-INDEX.
               DISPLAY "今からお前の名前は" IN-NAME(RESULT-INDEX:1)
                "だ。いいかい、" IN-NAME(RESULT-INDEX:1)
                "だよ。分かったら返事をするんだ、" IN-NAME(RESULT-INDEX:1)
                "!!".
               STOP RUN.
          *
          **********************************************************
          * N文字目を決める(in:IN-NAME out:RESULT-INDEX)
          **********************************************************
           TAKE-AWAY-STRING      SECTION.
           TAKE-AWAY-STRING-RTN.
          *    乱数シードのために現在時刻を取る
               MOVE  FUNCTION CURRENT-DATE          TO  DATE-NOW.
               MOVE  FUNCTION NUMVAL(DATE-NOW-FFSS) TO  SEED-VAL.
          *    乱数は0以上1未満で作成される
               MOVE  FUNCTION RANDOM(SEED-VAL)  TO  RAND-VAL.
          *     DISPLAY RAND-VAL.
          *    乱数と文字長を掛けて何文字目かを決定する
               MULTIPLY RAND-VAL BY INPUT-SIZE GIVING RESULT-INDEX.
               IF RESULT-INDEX = 0 THEN
                   MOVE 1 TO  RESULT-INDEX
               END-IF.
           TAKE-AWAY-STRING-EXT.
               EXIT.
          **********************************************************
          * 入力文字数カウント(in:IN-NAME out:INPUT-SIZE)
          **********************************************************
           GET-INPUT-SIZE      SECTION.
           GET-INPUT-SIZE-RTN.
               INITIALIZE INPUT-SIZE.
               PERFORM VARYING TMP-IDX FROM 1 BY 1
                                  UNTIL TMP-IDX  > 40
          *       DISPLAY "char: " IN-NAME(TMP-IDX:1)
                 IF IN-NAME(TMP-IDX:1) = SPACE THEN
                   EXIT PERFORM
                 END-IF
                 ADD 1 TO INPUT-SIZE
               END-PERFORM.
           GET-INPUT-SIZE-EXT.
               EXIT.
    
    비록 고전했지만 그래도 일련의 처리를 마쳤다.당장 실행해봐.

    문자 출력을 빼앗는 느낌이 좋습니다.그러나

    \2바이트 문자!!/
    COBOL의 일부 참조는 바이트 단위이므로 2바이트 문자를 고려해야 합니다.
    투덜거리려면 방법이 있겠지만 같은 내용을 많이 썼으니 편한 함수가 없는 것 같다.
    확인해 보기로 마음먹었다sjis 문자 인코딩 테이블.
    첫 번째 바이트를 확인하면, 그것이 한 바이트인지 두 바이트인지 판단할 수 있다
    COBOL의 제어에 편입해 보십시오.반각 가명의 범위를 잊지 마라.
          * 全角半角判定
                 IF (IN-NAME(TMP-IDX:1) >= X"00" AND
                     IN-NAME(TMP-IDX:1)  <= X"7F") OR -- ascii
                    (IN-NAME(TMP-IDX:1) >= X"A1" AND
                     IN-NAME(TMP-IDX:1)  <= X"DF") THEN -- 半角カナ
          *          DISPLAY "半角:" IN-NAME(TMP-IDX:1)
                 ELSE
          *          DISPLAY "全角:" IN-NAME(TMP-IDX:2)
                    ADD 1 TO TMP-IDX                 -- 次の文字までIndexをずらす
                 END-IF
    
    첫 번째 바이트의 문자 범위를 검사합니다. 두 바이트의 문자라면 두 바이트로 설명합니다.
    (정의 밖의 영역을 어떻게 처리해야 할지 몰라서 두 바이트를 먼저 칩니다.)

    코드(최종 버전)


    길어서 접고 있어요.
           IDENTIFICATION DIVISION.
           PROGRAM-ID. coba-ba.
           AUTHOR. Keita INAGAKI.
           ENVIRONMENT DIVISION.
           CONFIGURATION SECTION.
           DATA DIVISION.
           WORKING-STORAGE SECTION.
          *
           01  IN-NAME         PIC X(40).
           01  RAND-VAL        PIC V9(10).
           01  INPUT-BYTES     PIC 9(5).
           01  INPUT-SIZE      PIC 9(5).
           01  TMP-IDX         PIC 9(5).
           01  TMP-SIZE        PIC 9(5).
           01  RESULT-INDEX    PIC 9(5).
           01  RESULT-STR      PIC X(10).
           01  RESULT-BYTES    PIC 9(1).
           01  SEED-VAL        PIC 9(5).
          * 乱数のシードに渡すのは0~32767のため、分秒4桁を渡す
           01  DATE-NOW.
               03  DATE-NOW-YY        PIC X(04).
               03  DATE-NOW-MM        PIC X(02).
               03  DATE-NOW-DD        PIC X(02).
               03  DATE-NOW-HH        PIC X(02).
               03  DATE-NOW-FFSS      PIC X(04).
          *
          ******************************************************************
          *  PROCEDURE DIVISION
          ******************************************************************
           PROCEDURE DIVISION.
           CNTL SECTION.
          *    メッセージ出力
               DISPLAY "契約書だよ。そこに名前を書きな。".
          *    コンソール入力を受け取る
               ACCEPT IN-NAME      FROM CONSOLE.
          *    入力文字長の取得
               PERFORM GET-INPUT-BYTES.
          *    受け取った名前を出力
               DISPLAY "フン。"
                       IN-NAME(1:INPUT-BYTES)
                       "というのかい。贅沢な名"
                       "だねぇ。".
          *    文字を奪う
               PERFORM TAKE-AWAY-STRING.
          *     DISPLAY RESULT-INDEX.
          *     全角半角で取得バイト数を変えるため、処理変更
          *     DISPLAY "今からお前の名前は" IN-NAME(RESULT-INDEX:1)
          *      "だ。いいかい、" IN-NAME(RESULT-INDEX:1)
          *      "だよ。分かったら返事をするんだ、" IN-NAME(RESULT-INDEX:1)
          *      "!!".
               PERFORM GET-STR-BY-INDEX.
               DISPLAY "今からお前の名前は"
                      RESULT-STR(1:RESULT-BYTES)
                      "だ。いいかい、"
                      RESULT-STR(1:RESULT-BYTES)
                      "だよ。分かったら返事をするんだ、"
                      RESULT-STR(1:RESULT-BYTES)
                      "!!".
               STOP RUN.
          *
          **********************************************************
          * N文字目を決める(in:IN-NAME out:RESULT-INDEX)
          **********************************************************
           TAKE-AWAY-STRING      SECTION.
           TAKE-AWAY-STRING-RTN.
          *    乱数シードのために現在時刻を取る
               MOVE  FUNCTION CURRENT-DATE          TO  DATE-NOW.
               MOVE  FUNCTION NUMVAL(DATE-NOW-FFSS) TO  SEED-VAL.
          *    乱数は0以上1未満で作成される
               MOVE  FUNCTION RANDOM(SEED-VAL)  TO  RAND-VAL.
          *     DISPLAY RAND-VAL.
          *    入力文字長を取得する
               PERFORM GET-INPUT-SIZE.
          *     DISPLAY INPUT-SIZE.
          *    乱数と文字長を掛けて何文字目かを決定する
               MULTIPLY RAND-VAL BY INPUT-SIZE GIVING RESULT-INDEX.
               IF RESULT-INDEX = 0 THEN
                   MOVE 1 TO  RESULT-INDEX
               END-IF.
           TAKE-AWAY-STRING-EXT.
               EXIT.
          **********************************************************
          * 入力バイト数カウント
          * in : IN-NAME
          * out: INPUT-BYTES
          **********************************************************
           GET-INPUT-BYTES      SECTION.
           GET-INPUT-BYTES-RTN.
               INITIALIZE INPUT-BYTES.
               PERFORM VARYING TMP-IDX FROM 1 BY 1
                                  UNTIL TMP-IDX  > 40
                 IF IN-NAME(TMP-IDX:1) = SPACE THEN
                   EXIT PERFORM
                 END-IF
                 ADD 1 TO INPUT-BYTES
               END-PERFORM.
           GET-INPUT-BYTES-EXT.
               EXIT.
          **********************************************************
          * 入力文字数カウント
          * in : IN-NAME
          * out: INPUT-SIZE
          **********************************************************
           GET-INPUT-SIZE      SECTION.
           GET-INPUT-SIZE-RTN.
               INITIALIZE INPUT-SIZE.
               PERFORM VARYING TMP-IDX FROM 1 BY 1
                                  UNTIL TMP-IDX  > 40
          *       DISPLAY "char: " IN-NAME(TMP-IDX:1)
                 IF IN-NAME(TMP-IDX:1) = SPACE THEN
                   EXIT PERFORM
                 END-IF
                 ADD 1 TO INPUT-SIZE
          * 全角半角判定
                 IF (IN-NAME(TMP-IDX:1) >= X"00" AND
                     IN-NAME(TMP-IDX:1)  <= X"7F") OR
                    (IN-NAME(TMP-IDX:1) >= X"A1" AND
                     IN-NAME(TMP-IDX:1)  <= X"DF") THEN
          *          DISPLAY "半角:" IN-NAME(TMP-IDX:1)
                 ELSE
          *          DISPLAY "全角:" IN-NAME(TMP-IDX:2)
                    ADD 1 TO TMP-IDX
                 END-IF
               END-PERFORM.
           GET-INPUT-SIZE-EXT.
               EXIT.
          **********************************************************
          * 入力文字数カウント
          * in : RESULT-INDEX
          * out: RESULT-STR
          **********************************************************
           GET-STR-BY-INDEX    SECTION.
           GET-STR-BY-INDEX-RTN.
               INITIALIZE TMP-SIZE.
               PERFORM VARYING TMP-IDX FROM 1 BY 1
                                  UNTIL TMP-IDX  > 40
                 IF IN-NAME(TMP-IDX:1) = SPACE THEN
                   EXIT PERFORM
                 END-IF
          * 全角半角判定
                 ADD 1 TO TMP-SIZE
          *       DISPLAY "char: " IN-NAME(TMP-IDX:1)
                 IF TMP-SIZE = RESULT-INDEX THEN
                   IF (IN-NAME(TMP-IDX:1) >= X"00" AND
                       IN-NAME(TMP-IDX:1)  <= X"7F") OR
                      (IN-NAME(TMP-IDX:1) >= X"A1" AND
                       IN-NAME(TMP-IDX:1)  <= X"DF") THEN
                      MOVE IN-NAME(TMP-IDX:1) TO RESULT-STR
                      MOVE 1                  TO RESULT-BYTES
                   ELSE
                      MOVE IN-NAME(TMP-IDX:2) TO RESULT-STR
                      MOVE 2                  TO RESULT-BYTES
                   END-IF
          *         DISPLAY "RESULT BECOME " RESULT-STR
                   EXIT PERFORM
                 END-IF
                 IF (IN-NAME(TMP-IDX:1) >= X"00" AND
                     IN-NAME(TMP-IDX:1)  <= X"7F") OR
                    (IN-NAME(TMP-IDX:1) >= X"A1" AND
                     IN-NAME(TMP-IDX:1)  <= X"DF") THEN
          *
                 ELSE
                    ADD 1 TO TMP-IDX
                 END-IF
               END-PERFORM.
           GET-STR-BY-INDEX-EXT.
               EXIT.
    
    실행 결과는 다음과 같다!

    전각/반각/반각 가명으로 문자를 빼앗는 데 성공했습니다!
    물론 문자를 공백으로 입력하면 오류가 발생합니다.

    이걸로 코블 버전 국물로 하겠습니다, 어머님.

    끝말


    나는 고급 언어의 소중함을 절실히 느꼈다.
    그러나 이번 합작 덕분에 나는 지금까지 경원하던 문자 코드에 직면하여 한층 더 이해할 수 있었다
    국물에 힘쓰는 게 너무 좋은 것 같아서요.감사합니다.

    좋은 웹페이지 즐겨찾기