リファクタリングします。
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:~$
コメント