例題4)合計と割合(%)  2次元配列と繰り返し ファイル入力

 次のような3ヶ月分の家計の支出データがある。

家計支出データ
支出費目1月
金額(円)
2月
金額(円)
3月
金額(円)
食費55,21058,90063,630
住居費87,00087,00087,000
水道・光熱費12,65015,65013,160
被服費23,4005,6000
保健医療費5,20003,500
理容衛生費3,2208,9703,500
交際費15,0003,00025,000
交通・通信費13,61025,37035,080
教育費07505,800
教養娯楽費3,9259,05315,093
その他16,79027,6586,234

 このデータをファイルに作成したものを次に示す。ファイル名は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ヶ月の支出金額を読み込む。月ごとに、各支出費目の支出合計に対する割合(パーセント)を計算する。また、支出費目と支出合計について3ヶ月の平均を求める。

 a) の例題ではデータが1ヶ月分だけでしたので1次元配列を使用してプログラムを作成しました。今度はデータが2ヶ月分以上ありますので、2次元配列を用いてプログラムを作成します。

2次元配列を使用したプログラムの例
プログラム
 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
c Example 4 平均と割合(%) 2次元配列と繰り返し
c  建築学科 2年  xxxxxxx  my name
c234567890  File = reidai4.f
      integer a(21,5),n,m,i,j
      real  per(21,5)
      data  a,per/105*0,105*0.0/,m/3/
c  ファイルを開く
      open(11,file='reidai4.dat',status='old')
c  データの読み込み
      n=1
  101 read(11,102,end=110)  (a(n,j),j=1,m)
      n=n+1
      go to 101
  102 format(12x,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(real(a(i,m+1))/real(m))
   30 continue
c  割合(%)の計算
      do  40  i=1, n+1
        do  50  j=1, m
          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(5x, 3(i10,' 月',4x),a12/5x, 4(6x,'金額(  % )')) 
      do  60  i=1, n      
        write(6,201) i,(a(i,j),per(i,j),j=1,m),a(i,m+1)
  201 format(i5, 4(i10:,'(',f5.1,')'))
   60 continue
      write(6,202) (a(n+1,j),per(n+1,j),j=1,m),a(n+1,m+1)
  202 format(' 合計', 4(i10:,'(',f5.1,')'))
      end

 このプログラムで使用されている主な文を説明します。

4行目       integer a(21,5),n,m,i,j

 integer文を用いて、寸法が 1から 21、1から 5 (21×5) の2次元配列 a と変数 n、m、i、j を整数型と定義します。配列 a には、11×3個の支出金額データ、各月の支出合計、各支出費目の平均を格納できるように十分な大きさを確保しておきます。

5行目       real  per(21,5)

 割合の計算結果を格納するために、real文を用いて、大きさが 21×5 の2次元配列 per を実数型と定義します。

6行目       data  a,per/105*0,105*0.0/,m/3/

 data文を用いて、配列 a と per に初期値ゼロを、変数 m に月数 3を設定します。105*0 の指定は、0 を105(21×5)個カンマ , で区切って並べたのと同じです。

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

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

10行目             n=1
11行目         101 read(11,102,end=110)  (a(n,j),j=1,m)
12行目             n=n+1
13行目             go to 101
14行目         102 format(12x,3i6)
15行目         110 continue

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

16行目             n=n-1

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

18行目             close(11)

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

20行目       do  10  j=1, m
21行目         do  20 i=1, n
22行目           a(n+1,j)=a(n+1,j)+a(i,j)
23行目    20   continue
24行目    10 continue

 20行目から24行目までは、月毎の支出合計を求めている部分です。ここでは2重のdo文を使用しています。
 21行目から23行目までの内側のdoでは、配列 a の n+1 行目に支出費目の金額を足し込んで月毎の支出合計を求めています。
外側のdoでは、doの範囲を m 回(ここでは 3回)繰り返すことを指定しています。

26行目       do  30  i=1, n+1
27行目         do  35 j=1, m
28行目           a(i,m+1)=a(i,m+1)+a(i,j)
29行目    35   continue
30行目         a(i,m+1)=nint(real(a(i,m+1))/real(m))
31行目    30 continue

 26行目から31行目までは、支出費目毎の3ヶ月の平均と支出合計の平均を求めている部分です。ここでは2重のdo文を使用しています。
 27行目から29行目までの内側のdoでは、配列 a の m+1 列目に各月の支出費目の金額を足し込んで費目毎の3ヶ月の合計を求めています。
 外側のdoでは、doの範囲(内側のdoと23行目の平均を求める部分)を支出合計の3ヶ月の合計と平均の計算も含めて n+1 回繰り返すことを指定しています。
 30行目では、小数点以下まで求めた平均をnint関数で四捨五入して整数値に変換し m+1 列目に格納しています。

33行目       do  40  i=1, n+1
34行目         do  50  j=1, m
35行目           per(i,j)=real(a(i,j))/real(a(n+1,j))*100.0
36行目    50   continue
37行目    40 continue

 33行目から37行目までは、割合の計算をする部分です。ここでは2重のdo文を使用しています。
 34行目から36行目までの内側の doでは、配列 a の各行の要素(各支出費目)を n+1 行目の各月の支出合計で割り 100.0 をかけて%を求めています。
外側のdoでは、内側の doを支出合計の割合(当然100%)の計算も含めて n+1 回繰り返すことを指定しています。

39行目       write(6,200) (i,i=1,m),'平均'
40行目   200 format(5x, 3(i10,' 月',4x),a12/5x, 4(6x,'金額(  % )')) 
41行目       do  60  i=1, n   
42行目         write(6,201) i,(a(i,j),per(i,j),j=1,m),a(i,m+1)
43行目   201 format(i5, 4(i10:,'(',f5.1,')'))
44行目    60 continue
45行目       write(6,202) (a(n+1,j),per(n+1,j),j=1,m),a(n+1,m+1)
46行目   202 format(' 合計', 4(i10:,'(',f5.1,')'))  
 39行目から46行目までは、計算結果を装置番号6の装置に書式仕様を用いて出力します。書式仕様の詳細は次の例題5で説明します。

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

 装置番号6(ここではディスプレイ)に出力される実行結果は次のようになります。

              1 月             2 月             3 月            平均
           金額(  % )      金額(  % )      金額(  % )      金額(  % )
    1     55210( 23.4)     58900( 24.3)     63630( 24.7)     59247
    2     87000( 36.9)     87000( 36.0)     87000( 33.7)     87000
    3     12650(  5.4)     15650(  6.5)     13160(  5.1)     13820
    4     23400(  9.9)      5600(  2.3)         0(  0.0)      9667
    5      5200(  2.2)         0(  0.0)      3500(  1.4)      2900
    6      3220(  1.4)      8970(  3.7)      3500(  1.4)      5230
    7     15000(  6.4)      3000(  1.2)     25000(  9.7)     14333
    8     13610(  5.8)     25370( 10.5)     35080( 13.6)     24687
    9         0(  0.0)       750(  0.3)      5800(  2.2)      2183
   10      3925(  1.7)      9053(  3.7)     15093(  5.9)      9357
   11     16790(  7.1)     27658( 11.4)      6234(  2.4)     16894
 合計    236005(100.0)    241951(100.0)    257997(100.0)    245318



Fortranの文法参照