COBOL로 탕시어머니~ 2바이트 문자판정법~
개시하다
@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.
실행 결과는 다음과 같다!전각/반각/반각 가명으로 문자를 빼앗는 데 성공했습니다!
물론 문자를 공백으로 입력하면 오류가 발생합니다.
이걸로 코블 버전 국물로 하겠습니다, 어머님.
끝말
나는 고급 언어의 소중함을 절실히 느꼈다.
그러나 이번 합작 덕분에 나는 지금까지 경원하던 문자 코드에 직면하여 한층 더 이해할 수 있었다
국물에 힘쓰는 게 너무 좋은 것 같아서요.감사합니다.
Reference
이 문제에 관하여(COBOL로 탕시어머니~ 2바이트 문자판정법~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Keita_INAGAKI/items/6bb0551a483379a94229텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)