FORTRAN(cutコマンドを作るその7)

旧2-5. Fortran毎日学習

リファクタリングします。
FORTRANの部分文字列抽出が活かせてなかったので、DISP_LOC配列の使い方を変えます。
二次元配列にして、2値で範囲を設定するようにします。範囲がない値の場合は、2値は同じ値になります。
このような関数になりました。DISP_LOCはOPT_INFOという名前に変更して、SSTRING1やSSTRING2も、COMMA_STRとHYPHEN_STRに変更しました。

 2000 SUBROUTINE B_OPT(B_OPT_STRING,COMMA_SIZE,OPT_INFO)
        CHARACTER*100 B_OPT_STRING,COMMA_STR(10),HYPHEN_STR(10)
        INTEGER OPT_INFO(100,2),COMMA_SIZE,HYPHEN_SIZE

        CALL SPLIT(B_OPT_STRING,',', COMMA_STR,COMMA_SIZE)
        DO 2100 I=1,COMMA_SIZE
          CALL SPLIT(COMMA_STR(I),'-', HYPHEN_STR,HYPHEN_SIZE)
          IF(HYPHEN_SIZE.EQ.1) THEN
            READ(COMMA_STR(I),*) L
            M = L
          ELSE
            READ(HYPHEN_STR(1),*) L
            READ(HYPHEN_STR(2),*) M
          END IF

          OPT_INFO(I,1) = L
          OPT_INFO(I,2) = M
 2100   CONTINUE
      END

これに伴って他関数もリファクタリングした全ソースがこれです。

akk@deb9:~$ cat -n cut7.f
     1   1000 PROGRAM MAIN
     2          CHARACTER*100 LINE,ARGS
     3          INTEGER OPT_INFO(100,2),OPT_SIZE
     4
     5          N = IARGC()
     6          DO 1300 I=1,N
     7            CALL GETARG(I,ARGS)
     8
     9            IF(ARGS(1:2).EQ.'-b') THEN
    10              CALL B_OPT(ARGS(3:),OPT_SIZE,OPT_INFO)
    11            ELSE
    12              OPEN(UNIT=10,FILE=ARGS(1:INDEX(ARGS,' ')-1),
    13       1      STATUS='OLD',
    14       2      ACCESS='SEQUENTIAL')
    15   1100       READ(10,*,END=1200) LINE
    16              CALL CUT(LINE,OPT_SIZE,OPT_INFO)
    17              GOTO 1100
    18   1200       CLOSE(10,STATUS='KEEP')
    19            END IF
    20   1300   CONTINUE
    21          STOP
    22        END
    23
    24   2000 SUBROUTINE B_OPT(B_OPT_STRING,COMMA_SIZE,OPT_INFO)
    25          CHARACTER*100 B_OPT_STRING,COMMA_STR(10),HYPHEN_STR(10)
    26          INTEGER OPT_INFO(100,2),COMMA_SIZE,HYPHEN_SIZE
    27
    28          CALL SPLIT(B_OPT_STRING,',', COMMA_STR,COMMA_SIZE)
    29          DO 2100 I=1,COMMA_SIZE
    30            CALL SPLIT(COMMA_STR(I),'-', HYPHEN_STR,HYPHEN_SIZE)
    31            IF(HYPHEN_SIZE.EQ.1) THEN
    32              READ(COMMA_STR(I),*) L
    33              M = L
    34            ELSE
    35              READ(HYPHEN_STR(1),*) L
    36              READ(HYPHEN_STR(2),*) M
    37            END IF
    38
    39            OPT_INFO(I,1) = L
    40            OPT_INFO(I,2) = M
    41   2100   CONTINUE
    42        END
    43
    44   3000 SUBROUTINE CUT(LINE,OPT_SIZE,OPT_INFO)
    45          INTEGER OPT_SIZE,OPT_INFO(100,2)
    46          CHARACTER*100 LINE
    47          DO 3100 I=1,OPT_SIZE
    48            J = OPT_INFO(I,1)
    49            K = OPT_INFO(I,2)
    50            WRITE(*,3300) LINE(J:K)
    51   3100   CONTINUE
    52          WRITE(*,*) ''
    53   3200   RETURN
    54   3300   FORMAT(A$)
    55        END
    56
    57  10000 SUBROUTINE SPLIT(SRC,SEP,DEST,SPLIT_SIZE)
    58          CHARACTER*100 SRC,DEST(10)
    59          CHARACTER*1 SEP
    60          INTEGER IND,S1,S2,RSLT,SPLIT_SIZE
    61          IND = 0
    62          S2 = -1
    63          I = 1
    64  10100   RSLT = INDEX(SRC(IND+1:),SEP)
    65          IF(RSLT.NE.0) THEN
    66            S1 = IND + 1
    67            IND = IND + RSLT
    68            S2 = IND - 1
    69            DEST(I) = SRC(S1:S2)
    70            I = I + 1
    71            GOTO 10100
    72          END IF
    73          DEST(I) = SRC(S2+2:)
    74          SPLIT_SIZE = I
    75          RETURN
    76        END
    77
takk@deb9:~$

FORTRANは、まだスラスラ書けるというわけではないですが、ようやくプログラミングらしくなってきた気がします。

実行結果です。

takk@deb9:~$ gfortran -fdollar-ok cut7.f
takk@deb9:~$ ./a.out -b1-5 x00
10010
10110
10210
10310
10410
10510
10610
10710
10810
10910
takk@deb9:~$ ./a.out -b1-3,5 x00
1000
1010
1020
1030
1040
1050
1060
1070
1080
1090
takk@deb9:~$ ./a.out -b1,3,5 x00
100
110
120
130
140
150
160
170
180
190
takk@deb9:~$

コメント

タイトルとURLをコピーしました