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


コメント