compare -- ファイルの比較 ― 2015年03月01日 09:52
ファイルの入出力ができたので、ファイルを使った小さいプログラムの紹介をします。
まずは、compareです。
compare file1 file2
file1とfile2を比較して、違っていたら表示します。まずは、RATFOR版から、
# compare2.r4 -- compare two files for equality character arg1(MAXLINE), arg2(MAXLINE) character line1(MAXLINE), line2(MAXLINE) integer getarg, equal, fopen, getlin integer infil1, infil2, lineno, m1, m2 if (getarg(1, arg1, MAXLINE) == EOF | getarg(2, arg2, MAXLINE) == EOF) then call error('usage: compare file1 file2.') if (fopen(infil1, arg1, READ) == ERR) call cant(arg1) if (fopen(infil2, arg2, READ) == ERR) call cant(arg2) lineno = 0 repeat { m1 = getlin(line1, infil1) m2 = getlin(line2, infil2) if ((m1 == EOF) | (m2 == EOF)) break lineno = lineno + 1 if (equal(line1,line2) == NO) call difmsg(lineno,line1,line2) } if (m1 == EOF & m2 != EOF) call remark('eof on file 1.') else if (m1 != EOF & m2 == EOF) call remark('eof on file 2.') stop end
まずは、引数を検査し入力ファイルをオープンします。次に、それぞれ1行ずつ読み込みながら 、逐次、比較し差違があれば、出力します。Watcom Fortran77版は、下記の通り。
c compare2.for -- compare two files for equality program compare integer*1 arg1(82), arg2(82) ! MAXLINE(82) integer*1 line1(82), line2(82) ! MAXLINE(82) integer getarg, equal, fopen , getlin integer infil1, infil2, lineno, m1, m2 call initfile() if (getarg(1,arg1,82) .eq. -1) then ! MAXLINE(82) EOF(-1) call error('1:usage: compare2 file1 file2.') else if (getarg(2,arg2,82) .eq. -1) then ! MAXLINE(82) EOF(-1) call error('2:usage: compare2 file1 file2.') end if if (fopen(infil1,arg1,82) .ne. 1) then ! READ(82) YES(1) call cant(arg1) end if if (fopen(infil2,arg2,82) .ne. 1) then ! READ(82) YES(1) call cant(arg2) end if lineno = 0 loop m1 = getlin(line1,infil1) m2 = getlin(line2,infil2) if ((m1 .eq. -1) .or. (m2 .eq. -1)) then ! EOF(-1) exit end if lineno = lineno + 1 if (equal(line1,line2) .ne. 1) then ! YES(1) call difmsg(lineno,line1,line2) end if end loop if ((m1 .eq. -1) .and. (m2 .ne. -1)) then call remark('eof on file 1.') else if ((m1 .ne. -1) .and. (m2 .eq. -1)) then call remark('eof on file 2.') end if call fclose(infil1) call fclose(infil2) stop end
ファイルは、getlin()を使って行単位で、読み込みます。fgetc()を使って下記のようになります。
c getlin.for -- get line from infile integer function getlin(line,u) integer*1 line(*) integer u integer*1 c,fgetc integer col col = 1 while (fgetc(u,c) .ne. -1) do ! EOF(-1) line(col) = c col = col + 1 if (c .eq. 10) then ! NEWLINE(10) line(col) = -2 ! EOS(-2) getlin = col - 1 return end if end while getlin = -1 ! EOF(-1) return end
実際の比較は、equal()を使います。RATFOR版は下記の通り。
# equal.r4 -- compare str1 to str2; return YES if equal, NO if not integer function equal(str1,str2) character str1(ARB), str2(ARB) integer i for (i = 1; str1(i) == str2(i); i = i + 1) if (str1(i) .eq. EOS) { equal = YES return } equal = NO return end
Watcom Fortran77版は下記の通り。
c equal.for -- compare str1 to str2; return YES(1) if equal, NO(0) if not integer function equal(str1,str2) integer*1 str1(*),str2(*) integer i i = 1 while (str1(i) .eq. str2(i)) do if (str1(i) .eq. -2) then ! EOS(-2) equal = 1 ! YES(1) return end if i = i + 1 end while equal = 0 ! NO(0) return end
さて、差違のある行の打ち出しはdifmsg()を使います。RATFOR版は下記の通り。
# difmsg.r4 -- print line numbers and differing lines subroutine difmsg(lineno, line1, line2) integer lineno character line1(ARB), line2(ARB) call putdec(lineno, 5) call putc(NEWLINE) call putlin(line1, STDOUT) call putlin(line2, STDOUT) return end
Watcom Fortran77版は下記の通り。
c difmsg.for -- print line numbers and differing lines subroutine difmsg(lineno, line1, line2) integer lineno integer*1 line1(*), line2(*) ! ARB(*) ARB(*) call putdec(lineno, 5) call putc(10) ! NEWLINE(10) call putlin(line1, 6) ! STDOUT(6) call putlin(line2, 6) ! STDOUT(6) return end
行単位の出力は、putlin()を使います。これは、fputc()を使って、下記のようになります。
c putlin.for -- put lin to u subroutine putlin(lin,u) integer*1 lin(*) ! ARB(*) integer u,i i = 1 while (lin(i) .ne. -2) do ! EOS(-2) call fputc(u, lin(i)) i = i + 1 end while return end
include -- ファイルの読み込み ― 2015年03月14日 10:28
以前、ファイル関連のモジュールを作成したとき、ファイルの読み込み機能"include"を使いました。これは 、Watcom Fortran77のソースプログラム中にファイルを読み込むものでした。これ以外の用途には使えません。 汎用的に使えると便利そうです。include -- ファイルの読み込みを紹介します。
テキストファイル中に、別ファイルを取り込みます。
RATFOR版は下記の通り。
# include.r4 -- replace include file by contents of file character line(MAXLINE), str(MAXLINE) integer equal, getlin, getwrd, fopen integer infile(NFILES), len, level, loc string incul "include" infile(1) = STDIN for (level = 1; level > 0; level = level - 1) { while (getlin(line,infile(level)) != EOF) { loc = 1 len = getwrd(line,loc,str) if (equal(str,incul) .ne. 1) call putlin(line,STDOUT) else { level = level + 1 if (level .gt. NFILES) call error('includes nested deeply.') len = getwrd(line,loc,str) if (fopen(infile(level),str,READ) .eq. ERR) call cant(str) } } if (level .gt. 1) call fclose(infile(level)) } stop end
Watcom Fortran版は下記の通り。
c include.for -- replace include file by contents of file program include integer*1 line(82),str(82) ! MAXLINE(82) integer*1 getlin integer getwrd integer equal,fopen integer infile(10),len,level,loc ! NFILES(10) integer*1 incul(8) data incul /'i','n','c','l','u','d','e',-2/ ! EOS(-2) call initfile infile(1) = 5 ! STDIN(5) level = 1 while (level .gt. 0) do while (getlin(line,infile(level)) .ne. -1) do ! EOF(-1) loc = 1 len = getwrd(line,loc,str) if (equal(str,incul) .ne. 1) then call putlin(line,6) ! STDOUT(6) else level = level + 1 if (level .gt. 10) then ! NFILES(10) call error('includes nested deeply.') end if len = getwrd(line,loc,str) if (fopen(infile(level),str,82) .eq. -1) then ! READ(82) ERR(-1) call cant(str) endif end if end while if (level .gt. 1) then call fclose(infile(level)) end if level = level - 1 end while stop end
下請けルーチン、getwrd()は下記の通り。
# getwrd.r4 -- get non-blank word from in(i) into out, increment j integer function getwrd(in,i,out) character in(ARB),out(ARB) integer i,j while (in(i) == BLANK | in(i) == TAB) i = i + 1 j = 1 while (in(i) != EOS & in(i) != BLANK & in(i) != TAB & in(i) .ne. NEWLINE) { out(j) = in(i) i = i + 1 j = j + 1 } out(j) = EOS getwrd = j - 1 return end
Watcom Fortran77版は下記の通り。
c getwrd.for -- get non-blank word from in(i) into out, increment j integer function getwrd(in,i,out) integer*1 in(*),out(*) ! ARB(*) integer i,j while ((in(i) .eq. 32) .or. (in(i) .eq. 9)) do ! BLANK(32) TAB(9) i = i + 1 end while j = 1 while (in(i) .ne. -2 .and. in(i) .ne. 32 ! EOS(-2) BLANK(32) 1 .and. in(i) .ne. 9 .and. in(i) .ne. 10) do ! TAB(9) NEWLINE(10) out(j) = in(i) i = i + 1 j = j + 1 end while out(j) = -2 ! EOS(-2) getwrd = j - 1 return end
最近のコメント