Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reading array using format statements

Status
Not open for further replies.

oakleybloke

Technical User
Apr 20, 2011
3
GB
I am trying to read in data from an output file that has the form:


MAP=======================================================================================
Map of PRESSURE at 2 Jan 2000, 1.0 days
==========================================================================================

Layer iz= 1
ix= : 1 2 3 4 5
Row iy= 1: 298.888 298.888 298.888 298.888 298.888
Row iy= 2: 298.888 298.888 298.888 298.888 298.888
Row iy= 3: 298.888 298.888 298.888 298.888 298.889
Row iy= 4: 298.888 298.888 298.888 298.888 298.889
Row iy= 5: 298.888 298.888 298.888 298.888 298.889

I have tried using an implicit do loop, and a format statement to ignore the 'Row iy= 1: part and then read the next values using further format statements. At the moment my code for the format statement is:

29 FORMAT(13X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3)
So I skip the first 13 characters, reads the number, skips the next character and reads the number and so on.

My problem is that this is specific to the dimensions of the array and generally seems a bit ridiculous, is there a way to write format statements so that they include parameters such as the size of the array? Or should I be trying something completely different? My only other thought is that I could generate the code for the format statement somehow, using the array parameters, but I am unsure how to do this, and include it in my program.

I am also using FORTRAN 77.

Thanks Tom
 
have tried using an implicit do loop, and a format statement to ignore the 'Row iy= 1: part and then read the next values using further format statements.
........
Then post the code what have you tried so far

My problem is that this is specific to the dimensions of the array
........
When you have the number of columns, then you can use implicit do loop over the column index, i.e. something like
Code:
read(1,*,err=99) x(i), (a(i,j), j=1,n)
e.g. see
 
Hi,

Thanks for getting back to me, sorry, my code is as below, GRD_X is the number of columns, and GRD_Y is the number of rows in the data (relates to layers in a 3D grid). I get the output as shown below, in 7 columns and 43 rows I think , 300 data points altogether, so all the data is there just not in the layout I was expecting, and not repeatable if the dimensions of the array change (GRD_X and Y).

READ(10,29) ((PRESSURE1(i,j),i=1,GRD_X),j=1,GRD_Y)
29 FORMAT(13X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3
+,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3,2X,F7.3)

WRITE(11,*) ((PRESSURE1(i,j),i=1,GRD_X),j=1,GRD_Y)

Output:

Timestep: 1.00000
298.881 298.882 298.883 298.884 298.885 298.886 298.887
298.888 298.889 298.810 303.111 303.112 303.113 303.214
303.215 303.216 303.217 303.118 303.119 303.120 298.821
298.822 298.823 298.824 298.825 298.826 298.827 298.828
298.829 298.830 298.831 298.832 298.833 298.834 298.835
298.836 298.837 298.838 298.839 298.840 303.141 303.142
303.243 303.244 303.345 303.310 303.260 303.220 303.199
303.190 298.889 298.889 298.889 298.888 298.888 298.888

If I understand the second part of your reply correctly, I should be able to use the column index to loop over each row, will this ignore the data Row iy=1: etc?

Thanks for your help, I have only been used to working with simple numerical only examples so far, so picking through this output file is quite a learning curve.

Tom
 
I have figured this out now, my code is now:

DO j=1,GRD_Y
READ(10,*)ATEMP,BTEMP,CTEMP,(PRESSURE1(i,j),i=1,GRD_X)
ENDDO

I understand what you were suggesting now, thanks.
 
Hi oakleybloke,
The diswantage of your method is that it isn't flexible
Code:
READ(10,*)ATEMP,BTEMP,CTEMP,(PRESSURE1(i,j),i=1,GRD_X)
parses only the line of the form
Code:
Row iy=  1:  298.888  298.888  298.888  298.888  298.888
but it doen't work on line like this
Code:
Row iy=  1 :  298.888  298.888  298.888  298.888  298.888
or this
Code:
Row iy =  1:  298.888  298.888  298.888  298.888  298.888

Here is an example how to separate the numeric part from the line.
The subroutine process_line_01 is method you used - parsing only one type of line. The subroutine process_line_02 is more flexible - it parses only numeric data after ':'
oakleybloke.f95
Code:
[COLOR=#a020f0]program[/color] oakleybloke
[COLOR=#2e8b57][b]implicit[/b][/color] [COLOR=#2e8b57][b]none[/b][/color]

[COLOR=#2e8b57][b]integer[/b][/color] j
[COLOR=#2e8b57][b]character[/b][/color]([COLOR=#ff00ff]80[/color]) :: line
[COLOR=#2e8b57][b]real[/b][/color] :: a([COLOR=#ff00ff]5[/color])

[COLOR=#0000ff]! This works with method 01[/color]
line [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'Row iy=  1:  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#008080]call[/color] process_line_01([COLOR=#008080]adjustl[/color]([COLOR=#008080]trim[/color](line)), a, [COLOR=#ff00ff]5[/color])

[COLOR=#0000ff]! This doesn't work with method 01[/color]
[COLOR=#0000ff]! line = 'Row iy=  1 :  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#0000ff]! call process_line_01(adjustl(trim(line)), a, 5)[/color]

[COLOR=#0000ff]! This all work with method 02[/color]
line [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'Row iy=  1:  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#008080]call[/color] process_line_02([COLOR=#008080]adjustl[/color]([COLOR=#008080]trim[/color](line)), a, [COLOR=#ff00ff]5[/color])

line [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'Row iy=  1 :  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#008080]call[/color] process_line_02([COLOR=#008080]adjustl[/color]([COLOR=#008080]trim[/color](line)), a, [COLOR=#ff00ff]5[/color])

line [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'Row iy =  1 :  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#008080]call[/color] process_line_02([COLOR=#008080]adjustl[/color]([COLOR=#008080]trim[/color](line)), a, [COLOR=#ff00ff]5[/color])

line [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]'These are my numbers :  298.881  298.882  298.883  298.884  298.885'[/color]
[COLOR=#008080]call[/color] process_line_02([COLOR=#008080]adjustl[/color]([COLOR=#008080]trim[/color](line)), a, [COLOR=#ff00ff]5[/color])


[COLOR=#a020f0]end program[/color] oakleybloke

[COLOR=#a020f0]subroutine[/color] process_line_01(line, array, n)
  [COLOR=#0000ff]! input parameters[/color]
  [COLOR=#2e8b57][b]character[/b][/color]([COLOR=#804040][b]*[/b][/color]), [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]in[/b][/color]) :: line
  [COLOR=#2e8b57][b]integer[/b][/color], [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]in[/b][/color]) :: n

  [COLOR=#0000ff]! output parameters[/color]
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]dimension[/b][/color](n), [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]out[/b][/color]) :: array

  [COLOR=#0000ff]! temporary variables[/color]
  [COLOR=#2e8b57][b]character[/b][/color]([COLOR=#ff00ff]10[/color]) :: atemp, btemp, ctemp
  [COLOR=#2e8b57][b]integer[/b][/color] :: j

  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'Processing line :'[/color]
  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]"'"[/color], line, [COLOR=#ff00ff]"'"[/color]

  array [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]0[/color]
  [COLOR=#0000ff]! parse numbers from line[/color]
  [COLOR=#804040][b]read[/b][/color] (line,[COLOR=#804040][b]*[/b][/color]) atemp, btemp, ctemp, (array(j), j[COLOR=#804040][b]=[/b][/color][COLOR=#ff00ff]1[/color],n)    

  [COLOR=#0000ff]! print out resulting array[/color]
  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'Resulting array :'[/color]
  [COLOR=#804040][b]do[/b][/color] j[COLOR=#804040][b]=[/b][/color][COLOR=#ff00ff]1[/color], n
    [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'a['[/color],j,[COLOR=#ff00ff]']='[/color], array(j)
  [COLOR=#804040][b]end do[/b][/color]

  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) 
[COLOR=#a020f0]end subroutine[/color] process_line_01

[COLOR=#a020f0]subroutine[/color] process_line_02(line, array, n)
  [COLOR=#0000ff]! input parameters[/color]
  [COLOR=#2e8b57][b]character[/b][/color]([COLOR=#804040][b]*[/b][/color]), [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]in[/b][/color]) :: line
  [COLOR=#2e8b57][b]integer[/b][/color], [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]in[/b][/color]) :: n

  [COLOR=#0000ff]! output parameters[/color]
[COLOR=#2e8b57][b]  real[/b][/color], [COLOR=#2e8b57][b]dimension[/b][/color](n), [COLOR=#2e8b57][b]intent[/b][/color]([COLOR=#2e8b57][b]out[/b][/color]) :: array

  [COLOR=#0000ff]! temporary variables[/color]
  [COLOR=#2e8b57][b]character[/b][/color]([COLOR=#ff00ff]80[/color]) :: numeric_data
  [COLOR=#2e8b57][b]integer[/b][/color] :: j

  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'Processing line :'[/color]
  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]"'"[/color], line, [COLOR=#ff00ff]"'"[/color]

  [COLOR=#0000ff]! numeric_data part of line[/color]
  [COLOR=#804040][b]if[/b][/color] ([COLOR=#008080]index[/color](line,[COLOR=#ff00ff]':'[/color]) [COLOR=#804040][b]>[/b][/color] [COLOR=#ff00ff]0[/color]) [COLOR=#804040][b]then[/b][/color]
     numeric_data [COLOR=#804040][b]=[/b][/color] [COLOR=#008080]adjustl[/color](line([COLOR=#008080]index[/color](line,[COLOR=#ff00ff]':'[/color])[COLOR=#804040][b]+[/b][/color][COLOR=#ff00ff]1[/color]:))
     [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'numeric_data part of the line :'[/color]
     [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]"'"[/color], [COLOR=#008080]trim[/color](numeric_data), [COLOR=#ff00ff]"'"[/color]
  [COLOR=#804040][b]else[/b][/color]
     [COLOR=#0000ff]! take whole line[/color]
     numeric_data [COLOR=#804040][b]=[/b][/color] line
  [COLOR=#804040][b]end if[/b][/color]

  array [COLOR=#804040][b]=[/b][/color] [COLOR=#ff00ff]0[/color]
  [COLOR=#0000ff]! parse numbers from the numeric_data part of the line[/color]
  [COLOR=#804040][b]read[/b][/color] (numeric_data,[COLOR=#804040][b]*[/b][/color]) (array(j), j[COLOR=#804040][b]=[/b][/color][COLOR=#ff00ff]1[/color],n)    

  [COLOR=#0000ff]! print out resulting array[/color]
  [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'Resulting array :'[/color]
  [COLOR=#804040][b]do[/b][/color] j[COLOR=#804040][b]=[/b][/color][COLOR=#ff00ff]1[/color], n
    [COLOR=#804040][b]write[/b][/color] ([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) [COLOR=#ff00ff]'a['[/color],j,[COLOR=#ff00ff]']='[/color], array(j)
  [COLOR=#804040][b]end do[/b][/color]  

  [COLOR=#804040][b]write[/b][/color]([COLOR=#804040][b]*[/b][/color],[COLOR=#804040][b]*[/b][/color]) 
[COLOR=#a020f0]end subroutine[/color] process_line_02
Output:
Code:
$ g95 oakleybloke.f95 -o oakleybloke

$ oakleybloke
 Processing line :
 'Row iy=  1:  298.881  298.882  298.883  298.884  298.885'
 Resulting array :
 a[ 1 ]= 298.881
 a[ 2 ]= 298.882
 a[ 3 ]= 298.883
 a[ 4 ]= 298.884
 a[ 5 ]= 298.885

 Processing line :
 'Row iy=  1:  298.881  298.882  298.883  298.884  298.885'
 numeric_data part of the line :
 '298.881  298.882  298.883  298.884  298.885'
 Resulting array :
 a[ 1 ]= 298.881
 a[ 2 ]= 298.882
 a[ 3 ]= 298.883
 a[ 4 ]= 298.884
 a[ 5 ]= 298.885

 Processing line :
 'Row iy=  1 :  298.881  298.882  298.883  298.884  298.885'
 numeric_data part of the line :
 '298.881  298.882  298.883  298.884  298.885'
 Resulting array :
 a[ 1 ]= 298.881
 a[ 2 ]= 298.882
 a[ 3 ]= 298.883
 a[ 4 ]= 298.884
 a[ 5 ]= 298.885

 Processing line :
 'Row iy =  1 :  298.881  298.882  298.883  298.884  298.885'
 numeric_data part of the line :
 '298.881  298.882  298.883  298.884  298.885'
 Resulting array :
 a[ 1 ]= 298.881
 a[ 2 ]= 298.882
 a[ 3 ]= 298.883
 a[ 4 ]= 298.884
 a[ 5 ]= 298.885

 Processing line :
 'These are my numbers :  298.881  298.882  298.883  298.884  298.885'
 numeric_data part of the line :
 '298.881  298.882  298.883  298.884  298.885'
 Resulting array :
 a[ 1 ]= 298.881
 a[ 2 ]= 298.882
 a[ 3 ]= 298.883
 a[ 4 ]= 298.884
 a[ 5 ]= 298.885
The complete example how to read a file line by line is here:

Hope this helps you to strart.
 
The other possible solution is to transform your "complicated" data file before processing with fortran into simpler form.
If you are working on Unix or MSYS in windows, you have the utilities for this purpose: sed and awk.
For example:
Your file oakleybloke_data.dat
Code:
MAP=====================================================
Map of PRESSURE at  2 Jan 2000,     1.0 days  
========================================================

Layer iz=  1
 ix=   :        1        2        3        4        5        
Row iy=  1:  298.888  298.888  298.888  298.888  298.888  
Row iy=  2:  298.888  298.888  298.888  298.888  298.888  
Row iy=  3:  298.888  298.888  298.888  298.888  298.889  
Row iy=  4:  298.888  298.888  298.888  298.888  298.889  
Row iy=  5:  298.888  298.888  298.888  298.888  298.889
could be simply transformed using sed command
Code:
$ sed -e '1,5d;s/^.*:\s*//g' oakleybloke_data.dat > oakleybloke_data_temp.dat
into a simpler file oakleybloke_data_temp.dat
Code:
        1        2        3        4        5        
  298.888  298.888  298.888  298.888  298.888  
  298.888  298.888  298.888  298.888  298.888  
  298.888  298.888  298.888  298.888  298.889  
  298.888  298.888  298.888  298.888  298.889  
  298.888  298.888  298.888  298.888  298.889
Now you don't have problems to read data from oakleybloke_data_temp.dat using fortran.

You can call the above sed command directly from your fortran program using the system() function
 
FYI, here is an awk command
Code:
$ awk 'NR==6{print $NF}; NR>=7{gsub(/^.*:\s*/,"",$0);print $0}' oakleybloke_data.dat > oakleybloek_data_temp2.dat
which transforms your file into oakleybloke_data_temp2.dat

Code:
5
  298.888  298.888  298.888  298.888  298.888  
  298.888  298.888  298.888  298.888  298.888  
  298.888  298.888  298.888  298.888  298.889  
  298.888  298.888  298.888  298.888  298.889  
  298.888  298.888  298.888  298.888  298.889
On the first line is number of the columns, i.e dimension of the square matrix to be allocated in your fortran program for the data.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top