例題8 2次元配列とファイルへ出力

 次のようなデータファイルがある。このデータはアメダスで観測された1996年7月の東京の気温で1時間ごとに測定されたものである(前後の目盛りの行は除く)。書式仕様は(i2,24f4.1)でファイル名はreidai08.dである。

----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----
                                                          ←  1レコード目は空の行
     観測所番号:44131  東京                          ↓  5レコード目からデータ
          1996年07月   気温(0.1°C)
日   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24時
 1 255 251 249 249 246 250 250 259 269 275 279 292 299 301 304 301 292 289 282 261 254 253 256 250
 2 251 244 240 238 238 240 252 263 280 302 298 297 301 305 304 300 291 285 277 267 260 260 261 252
 3 247 240 247 239 237 238 242 258 265 282 292 303 300 299 286 281 264 261 221 218 215 207 209 209
                                             :
                                             :
31 279 276 275 273 273 277 283 300 310 317 321 327 318 321 311 305 296 291 288 286 286 287 285 280
----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----

 このデータを読み込んで次のプログラムを作成する。
1日毎の最高気温、最低気温、平均気温を計算し出力する。また1ヶ月のうちで最高気温が最高の日とその気温、最低気温が最低の日とその気温を求めて出力する。

 例題7では、データが1日分でしたが、例題8では31日分のデータを読み込んで1日毎の最高気温、最低気温、平均気温を求めます。

 例題8のフローチャートとプログラムの例を示します。

概要

プログラム
 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
59
60
61
62
63
64
65
66
c Example 8     2次元配列 ファイルへ出力
c  機械工学科 1年  xxxxxxx  my name
c         Filename = reidai08.f
      integer hour, day
      parameter (hour=24, day=31)
      real a(hour,day),av(day),amin(day),amax(day)
      data m/hour/
c   気温データを読む
      open(11,file='reidai08.d',status='old')
      do 1010 j=1,4
        read(11,*) 
 1010 continue
 1001 continue
      read(11,101,end=2001) n,(a(i,n),i=1,m)
      go to 1001
 2001 continue
      close(11)
c   1日毎の最高・最低気温、平均気温を求める
      do 2010 j=1,n
        asum=0.0
        wmin=99.0
        wmax=-99.0
        do 2020 i=1,m
          asum=asum+a(i,j)
          if(a(i,j).gt.wmax) wmax=a(i,j)
          if(a(i,j).lt.wmin) wmin=a(i,j)
 2020   continue
        av(j)=asum/real(m)
        amin(j)=wmin
        amax(j)=wmax
 2010 continue
c   1ヶ月の最高・最低気温を求める
      wmin=99.0
      wmax=-99.0
      do 2030 j=1,n
        if(amax(j).gt.wmax) then
          wmax=amax(j)
          imax=j
        end if
        if(amin(j).lt.wmin) then
          wmin=amin(j)
          imin=j
        end if
 2030 continue
c   出力
      write(*,601)
      do 3010 j=1,n
        write(*,602) j, amax(j), amin(j), av(j)
 3010 continue
      write(*,603) imax, amax(imax), imin, amin(imin)
c   ファイルへ出力
      open(12,file='reidai08out.d',status='new')
      write(12,601)
      do 3020 j=1,n
        write(12,602) j, amax(j), amin(j), av(j)
 3020 continue
      write(12,603) imax, amax(imax), imin, amin(imin)
      close(12)
      stop
  101 format(i2,24f4.1)
  601 format( '1996年7月の東京の気温'
     *           /' 日  最高気温  最低気温  平均気温')
  602 format(i3,3f10.1)
  603 format(/'  1ヶ月の最高気温',i3,'日',f5.1
     *                 ,'   最低気温',i3,'日',f5.1)
      end


 例題8のプログラム例について説明します。

 4行目から7行目は宣言文です。

4行目         integer hour, day
5行目         parameter (hour=24, day=31)
6行目         real a(hour,day),av(day),amin(day),amax(day)
7行目         data m/hour/

 5行目のparameter文で、定数名hour、dayを定義し、整定数 24 に hour、整定数 31 に day と名前(定数名という)をつけています。そして、その定数名を配列宣言子の寸法の指定やdata文に使用しています。
 宣言文は一般には指定する順番に決まりはありませんが、parameter文については他の宣言文との位置関係に注意してください。定数名について型宣言が必要な場合には、4行目の integer文のように、定数名を定義している parameter文より前に型宣言をしておかねばなりません。また、型宣言文やdata文の中で定数名を使用する場合には、その型宣言文やdata文より前にparameter文で定義されていなければなりません。
 6行目の型宣言文では、1から hour と1から day の寸法をもつ2次元配列 a, 1から day の寸法をもつ1次元配列 av, amin, amax を実数型と宣言しています。a は気温データ 24時分×31日分 を格納しておくため、av, amin, amax はそれぞれ31日分の平均気温、最低気温、最高気温を格納しておくために用意したものです。
 7行目のdata文では、m に初期値として定数 hour を設定しています。

 9行目から17行目はファイルからデータを読み込む部分です。

9行目         open(11,file='reidai08.d',status='old')

9行目のopen文でデータファイル(ファイル名 reidai08.d)を装置番号11の装置につなげて開きます。ファイルの先頭には見出しなどのデータでないレコードが4レコードありますので、10行目から12行目で、このレコードを読み飛ばします。11行目のread文では並びを空にしています。

10行目       do 1010 j=1,4
11行目         read(11,*) 
12行目  1010 continue

 13行目から16行目はファイルから1ヶ月分のデータを読み込む部分で、データの書式仕様は60行目のformat文です。

13行目  1001 continue
14行目       read(11,101,end=2001) n,(a(i,n),i=1,m)
15行目       go to 1001
16行目  2001 continue
                  :
60行目   101 format(i2,24f4.1)

14行目のread文で1日分のデータを読み込んだら、次行の go to 文で、次のデータを読むために文番号 1001 のcontinue文に無条件に戻します。データが終わりになったらファイル終了指定子により文番号 2001 のcontinue文に制御を移します。
 7月のデータは31日分ありますが、他の月のデータは31日分あるとは限りませんので、ファイル終了指定子を用いてデータ数の違いに対応できるようにしています。
 read文では、書式仕様(i2,24f4.1)にしたがって、まず日にちを変数 n に i2(2桁の整数)で読み込み、次に do 並び(配列要素 a(i,n) の i について1から m(ここでは24)まで)を f4.1(4桁の幅に小数点以下1桁)で読み込みます。

 17行目のclose文でファイルを閉じます。

17行目       close(11)

19行目から31行目は平均気温、最高気温、最低気温を求める部分です。「1日分の平均気温、最高気温、最低気温を求める」ことを日数分繰り返しますので、次に示すように do のループが2重の入れ子になっています。内側のループ(23行目から27行目)が1日分( i について1から m )、外側のループ(19行目から31行目)が1ヶ月分( j について1から n )です。

19行目       do 2010 j=1,n
   :
23行目         do 2020 i=1,m
   :
27行目  2020   continue
   :
31行目  2010 continue

 次の20行目から27行目は1日分の平均気温を求めるための合計、最高気温、最低気温を求める部分です。この部分は、配列 a が2次元配列であること以外は例題7と同じですので説明は省きます。これを19行目の do文と31行目の continue文により日数分繰り返します。

20行目         asum=0.0
21行目         wmin=99.0
22行目         wmax=-99.0
23行目         do 2020 i=1,m
24行目           asum=asum+a(i,j)
25行目           if(a(i,j).gt.wmax) wmax=a(i,j)
26行目           if(a(i,j).lt.wmin) wmin=a(i,j)
27行目  2020   continue

 外側の doループの中の28行目から30行目は、求めた1日の平均気温、最高気温、最低気温をそれぞれ配列要素 av(j), amax(j), amin(j) に格納しています。

19行目       do 2010 j=1,n
   :
28行目         av(j)=asum/real(m)
29行目         amin(j)=wmin
30行目         amax(j)=wmax
31行目  2010 continue

 33行目から44行目は1ヶ月の最高気温とその日にち、最低気温とその日にちを求める部分です。

33行目       wmin=99.0
34行目       wmax=-99.0
35行目       do 2030 j=1,n
36行目         if(amax(j).gt.wmax) then
37行目           wmax=amax(j)
38行目           imax=j
39行目         end if
40行目         if(amin(j).lt.wmin) then
41行目           wmin=amin(j)
42行目           imin=j
43行目         end if
44行目  2030 continue

このうち最高気温とその日にちを求める部分を抜き出した部分が次です。

34行目       wmax=-99.0
35行目       do 2030 j=1,n
36行目         if(amax(j).gt.wmax) then
37行目           wmax=amax(j)
38行目           imax=j
39行目         end if

最高気温の求め方は1日の最高気温の求め方と同じですが、気温だけでなくその日にち(配列要素の添え字に相当)も変数(ここではimax)に格納しておく必要があります。

 最低気温とその日にちを求める部分を次に抜き出します。

33行目       wmin=99.0
35行目       do 2030 j=1,n
40行目         if(amin(j).lt.wmin) then
41行目           wmin=amin(j)
42行目           imin=j
43行目         end if
44行目  2030 continue

最低気温の求め方は1日の最低気温の求め方と同じですが、気温だけでなくその日にち(配列要素の添え字に相当)も変数(ここではimin)に格納しておく必要があります。

 46行目から50行目は計算結果を出力する部分です。書式仕様には61行目から65行目のformat文を使用しています。

46行目       write(*,601)
47行目       do 3010 j=1,n
48行目         write(*,602) j, amax(j), amin(j), av(j)
49行目  3010 continue
50行目       write(*,603) imax, amax(imax), imin, amin(imin)
   :
61行目   601 format( '1996年7月の東京の気温'
62行目      *           /' 日  最高気温  最低気温  平均気温')
63行目   602 format(i3,3f10.1)
64行目   603 format(/'  1ヶ月の最高気温',i3,'日',f5.1
65行目      *                 ,'   最低気温',i3,'日',f5.1)

まず46行目のwrite文で見出しを出力します。このwrite文の並びはありませんが、文番号601のformat文の書式にしたがって、まず、文字列

1996年7月の東京の気温
を出力してから行を変えて文字列
 日  最高気温  最低気温  平均気温
を出力します。次にdo文の指定により48行目のwrite文をjについて1〜nまで繰り返します。このwrite文では、並びの j, amax(j), amin(j), av(j) を 書式(i3,3f10.1)で出力します。50行目のwrite文では文番号601のformat文の書式にしたがって、まず文字列
  1ヶ月の最高気温
に続けて日にちimaxをi3で、続けて文字列 日 と 最高気温 amax(imax) を f5.1(5桁の幅に小数点以下1桁まで)出力し、同様に最低気温の日にちiminと最低気温 amin(imin) を出力します。

 52行目から58行目は計算結果をファイルに出力する部分です。52行目のopen文でファイル(ファイル名 reidai08out.d)を status='new' の指定により新しく作成し、装置番号12の装置につなげます。すでに reidai08out.d のファイルが存在するときにはopenエラーになります。58行目のclose文でこのファイルを閉じます。

52行目       open(12,file='reidai08out.d',status='new')
53行目       write(12,601)
54行目       do 3020 j=1,n
55行目         write(12,602) j, amax(j), amin(j), av(j)
56行目  3020 continue
57行目       write(12,603) imax, amax(imax), imin, amin(imin)
58行目       close(12)

ファイルへの出力はディスプレイへ出力する場合と同じ書式仕様を使用していますので、ファイルへの出力結果はディスプレイへの出力結果とまったく同じです。

 例題8の出力結果は次のようになります。


1996年7月の東京の気温
 日  最高気温  最低気温  平均気温
  1      30.4      24.6      26.9
  2      30.5      23.8      27.1
  3      30.3      20.7      25.3
  4      28.5      20.1      24.3
             :
             :
 28      33.0      26.2      29.0
 29      32.7      26.6      29.3
 30      31.7      27.1      29.1
 31      32.7      27.3      29.4

  1ヶ月の最高気温 17日 34.4   最低気温  8日 17.4


Fortranの文法参照