例題5)文字処理、ファイル処理、書式仕様

 3ヶ月分(1月から3月)の家計の支出データファイルがある。このファイルはファイル名がreidai4.datで、次に示す形式である。

 支出データファイルの内容

----+----1----+----2----+----3----+----4    

食費         55210 58900 63630         ←1行目(ファイルはこの行から)
住居費       87000 87000 87000
水道・光熱費 12650 15650 13160
被服費       23400  5600     0
保健医療費    5200     0  3500
理容衛生費    3220  8970  3500
交際費       15000  3000 25000
交通・通信費 13610 25370 35080
教育費           0   750  5800
教養娯楽費    3925  9053 15093
その他       16790 27658  6234         ←ここまで

 支出データファイルには、費目名(12桁)と3ヶ月の支出金額(6桁ずつ3個)が、1行ずつ各支出費目について並べられている。

 次のプログラムを作成します。

 支出データファイルを読んで、各支出費目と支出合計の3ヶ月の平均を求め、各支出費目の支出合計に対する割合(パーセント)を各月と平均について計算する。また、計算結果は見やすい表にする。

 このプログラムは、例題4のプログラムを、次のように変更します。
 ・支出費目名をデータとして入力し、出力する(文字処理)。
 ・平均についても割合を計算する。
 ・計算結果を見やすい表にするため、書式仕様を用いる。
 次に、プログラムの例を示します。

例題5)のプログラム例
プログラム
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
c Example 5 平均と割合(%)、ファイル入出力、書式仕様
c  建築学科 2年  xxxxxxx  my name
c234567890  File = reidai5.f
      integer nmax,nm,mmax
      parameter (nmax=21,mmax=5,nm=nmax*mmax)
      integer a(nmax,mmax),n,m,i,j
      real  per(nmax,mmax)
      character himoku(nmax)*12
      data  a,per/nm*0,nm*0.0/,m/3/
c  ファイルを開く
      open(11,file='reidai4.dat',status='old')
c  データの読み込み
      n=1
  101 read(11,102,end=110)   himoku(n), (a(n,j),j=1,m)
      n=n+1
      go to 101
  102 format(a12,3i6)
  110 continue
      n=n-1
c  ファイルを閉じる
      close(11)
c  月毎の支出合計の計算
      do  10  j=1, m
        do  20 i=1, n
          a(n+1,j)=a(n+1,j)+a(i,j)
   20   continue
   10 continue
c  費目毎の3ヶ月の平均と支出合計の平均
      do  30  i=1, n+1
        do  35 j=1, m
          a(i,m+1)=a(i,m+1)+a(i,j)
   35   continue
        a(i,m+1)=nint(a(i,m+1)/real(m))
   30 continue
c  割合(%)の計算
      do  40  i=1, n+1
        do  50  j=1, m+1
          per(i,j)=real(a(i,j))/real(a(n+1,j))*100.0
   50   continue
   40 continue
c  出力
      write(6,200) (i,i=1,m),'平均'
  200 format(12x,3(i8,' 月',4x),7x,a4/'支出費目',4x,4(4x,'金額(  % )')) 
      do  60  i=1, n      
        write(6,201) himoku(i),(a(i,j),per(i,j),j=1,m+1)
  201 format(a12, 4(i8:,'(',f5.1,')'))
   60 continue
      write(6,202) (a(n+1,j),per(n+1,j),j=1,m+1)
  202 format('合計', 8x, 4(i8:,'(',f5.1,')'))
c  ファイル出力
      open(12,file='reidai5out.dat',status='new')
      write(12,200) (i,i=1,m),'平均'
      do  70  i=1, n      
        write(12,201) himoku(i),(a(i,j),per(i,j),j=1,m+1)
   70 continue
      write(12,202) (a(n+1,j),per(n+1,j),j=1,m+1)
      close(12)
      end

 このプログラムで新しく使用されている機能や文を説明します。

4行目       integer nmax,nm,mmax
5行目       parameter (nmax=21,mmax=5,nm=nmax*mmax)
6行目       integer a(nmax,mmax),n,m,i,j
7行目       real  per(nmax,mmax)
8行目       character himoku(nmax)*12
9行目       data  a,per/nm*0,nm*0.0/,m/3/

 4行目から9行目までは宣言文で、parameter文を使用して定数名nmax、mmax、nm を定義し、その定数名を配列宣言子の寸法の指定に、また、data文の中に使用しています。
 5行目の parameter文では、整定数 21 に nmax、整定数 5 に mmax と名前をつけ(この名前を定数名という)、nmax*mmax (定数式という)の値に nm と名前をつけています。定数式の定義のなかで使用される定数名は、その定数式より前にparameter文で定義されていなければなりません。
 宣言文は一般には指定する順番に決まりはありませんが、parameter文については他の宣言文との位置関係に注意してください。定数名について型宣言が必要な場合には、4行目の integer文のように、定数名を定義している parameter文より前に型宣言をしておかねばなりません。また、data文の中で定数名を使用する場合には、そのdata文より前にparameter文で定義されていなければなりません。

11行目       open(11,file='reidai4.dat',status='old')

 open文を用いて、支出データファイル(ファイル名 reidai4.dat)を装置番号11の装置に接続し、status='old' の指定によりファイル reidai4.dat が存在することを確認し、読み書きできる状態にします。

13行目             n=1
14行目         101 read(11,102,end=110)   himoku(n), (a(n,j),j=1,m)
15行目             n=n+1
16行目             go to 101
17行目         102 format(a12,3i6)
18行目         110 continue

 13行目から18行目までは、装置番号11に接続されたファイル(ここでは reidai4.dat)から支出データを読み込む部分です。
 13行目で、変数 n(ここでは支出費目数)に 1 を入れておきます。
14行目の read文では、文字型配列要素 himoku(n)に費目名を、整数型配列要素 a(n,j) に(変数jについて1から mまで、3ヶ月分の)金額を、文番号 102 の format文に記述された書式仕様 a12,3i6 にしたがって読み込んでいます。この例では1つのread文がデータファイルの1行分のデータを読み込みます。データを1行分読んだあと15行目で n の値をひとつ増し、16行目のgoto文で次のデータを読むために14行目に戻ります。データが終わりの時には文番号 110 の文へ実行を移します。

19行目             n=n-1

 支出費目数 n が実際の費目数よりもひとつ大きくなっていますので、19行目で減らしています。

21行目             close(11)

 データの読み込みが終わりましたので、close文により、ファイルと装置番号11との接続を切り離します。

 計算の部分は例題4のプログラムと全く同じですので説明を省略します。

 次の42行目から49行目までは、計算結果を見やすい表にして出力している部分です。表の見出しを出力する部分、各費目について出力する部分、支出合計について出力する部分に分けて説明します。

42行目       write(6,200) (i,i=1,m),'平均'
43行目   200 format(12x,3(i8,' 月',4x),7x,a4/'支出費目',4x,4(4x,'金額(  % )')) 

 この2行は表の各見出し

                   1 月           2 月           3 月           平均
支出費目        金額(  % )    金額(  % )    金額(  % )    金額(  % )
を出力する部分です。write文の並びの (i,i=1,m) は、do型並びで変数iの値を制御変数iについて 1 から m まで繰り返し並べるので、この並びは 1, 2, 3, '平均'となります。これを、文番号200 の format文の書式仕様にしたがって出力します。まず、12xで12桁分移動します。次の 3(   ) は( )の中を3回繰り返すという意味です。write文の並びの [先頭の 1 を i8(8桁の右詰)で、アポストロフィ編集記述子の3文字分の文字列 ' 月'、4桁移動] を、並びの2と3についても繰り返します。次に7桁移動して、文字列「平均」を a4(4桁の右詰)で出力します。斜線編集記述子 / があると、そこで改行します。2行目にはアポストロフィ編集記述子の8文字分の文字列 '支出費目'を出力して4桁移動し、[4桁の移動とアポストロフィ編集記述子の11文字分の文字列 '金額( % )'の出力] を4回繰り返します。

44行目       do  60  i=1, n      
45行目         write(6,201) himoku(i),(a(i,j),per(i,j),j=1,m+1)
46行目   201 format(a12, 4(i8:,'(',f5.1,')'))
47行目    60 continue

 44行目から47行目までは、支出費目ごとの計算結果(11行分)を出力する部分で、do変数i が1の時を例に取ると出力結果は、

食費           55210( 23.4)   58900( 24.3)   63630( 24.7)   59247( 24.2)
 となります。45行目のwrite文の並びを文番号201 の format文の書式仕様にしたがって出力します。まず、文字型配列の要素 himoku(i)を a12(12桁の右詰)で、次の 4(   ) は( )の中を4回繰り返すという意味です。整数型配列の要素a(i,1)を i8(8桁の右詰)で、アポストロフィ編集記述子の1文字分の文字列 '('、実数型配列の要素 per(i,1)を f5.1(5桁の幅を取って小数点以下1桁までを右詰)で、アポストロフィ編集記述子の1文字分の文字列 ')'を出力します。これをjについて m+1(ここでは 4)まで繰り返します。

48行目       write(6,202) (a(n+1,j),per(n+1,j),j=1,m+1)
49行目   202 format('合計', 8x, 4(i8:,'(',f5.1,')'))

 この2行は支出合計について出力する部分で

合計          236005(100.0)  241951(100.0)  257997(100.0)  245318(100.0)
のように出力されます。48行目のwrite文の並びを文番号202 の format文の書式仕様にしたがって出力します。まず、アポストロフィ編集記述子の4文字分の文字列 '合計'を出力し8桁移動します。次の 4(   ) は文番号201 format文と同じで a(n+1,j)とper(n+1,j) を jについて m+1(ここでは 4)まで繰り返します。
 このプログラム例では、各支出費目の出力と合計の出力を分けて記述していますが、文字型配列要素の himoku(n+1) に文字定数 '合計' を代入しておけば、文番号 201 のformat文の書式仕様で出力でき、合計の部分を各支出費目の出力のdo文に含めることができます。
 文番号 201 と 202 のformat文の書式仕様には、コロン編集記述子 : が使用されています。コロン編集記述子は入出力の並びに項目が残っていない時は、書式制御を終わりにし、項目が残っている時はそのまま続けます。このプログラムは、コロン編集記述子が有効に機能する例ではありませんが、例題3)の b のプログラムでは有効に機能しています。例題3)の b のプログラムで、: のある場合とない場合について比較してみましょう。

 format文は実行時に参照される文なので、そのプログラム単位の中であれば、どこに記述されていてもかまいません。編集記述子の詳細は書式仕様を参照してください。

 次の51行目から57行目までは、標準入出力装置(ディスプレイ)に出力した内容をファイル(ファイル名deidai5out.dat)にも出力する部分です。

51行目       open(12,file='reidai5out.dat',status='new')
52行目       write(12,200) (i,i=1,m),'平均'
53行目       do  70  i=1, n 
54行目         write(12,201) himoku(i),(a(i,j),per(i,j),j=1,m+1)
55行目    70 continue
56行目       write(12,202) (a(n+1,j),per(n+1,j),j=1,m+1)
57行目       close(12)

 open文を用いて、出力用ファイル(ファイル名 reidai5out.dat)を装置番号12の装置に接続し、status='new' の指定により新しくファイル reidai5out.dat を作成し、読み書きできる状態にします。既に同じ名前のファイルが存在するとエラーになります。
52行目から56行目までは、出力装置番号が12にしているだけで、標準入出力装置(ディスプレイ)に出力する部分とまったく同じです。
ファイルへの書き込みが終わったところで、close文により、ファイルと装置番号12との接続を切り離します。


 プログラムを翻訳し実行してみます。実行時にファイルreidai4.datが必要です。このリンクreidai4.datを右クリックし表示されたメニューの、「対象をファイルに保存」を選び各自のプログラムと同じ場所(フォルダ)にそのファイル名のまま保存します。ファイルの内容を確認したい時は秀丸エディタで開きます。実行結果は次のようになります。

                   1 月           2 月           3 月           平均
支出費目        金額(  % )    金額(  % )    金額(  % )    金額(  % )
食費           55210( 23.4)   58900( 24.3)   63630( 24.7)   59247( 24.2)
住居費         87000( 36.9)   87000( 36.0)   87000( 33.7)   87000( 35.5)
水道・光熱費   12650(  5.4)   15650(  6.5)   13160(  5.1)   13820(  5.6)
被服費         23400(  9.9)    5600(  2.3)       0(  0.0)    9667(  3.9)
保健医療費      5200(  2.2)       0(  0.0)    3500(  1.4)    2900(  1.2)
理容衛生費      3220(  1.4)    8970(  3.7)    3500(  1.4)    5230(  2.1)
交際費         15000(  6.4)    3000(  1.2)   25000(  9.7)   14333(  5.8)
交通・通信費   13610(  5.8)   25370( 10.5)   35080( 13.6)   24687( 10.1)
教育費             0(  0.0)     750(  0.3)    5800(  2.2)    2183(  0.9)
教養娯楽費      3925(  1.7)    9053(  3.7)   15093(  5.9)    9357(  3.8)
その他         16790(  7.1)   27658( 11.4)    6234(  2.4)   16894(  6.9)
合計          236005(100.0)  241951(100.0)  257997(100.0)  245318(100.0)

 これとまったく同じ内容のファイル(ファイル名reidai5out.dat)が作成されます。



Fortranの文法参照