tags:

views:

56

answers:

2

I have 2 dimensional table in file, which look like this:

11, 12, 13, 14, 15
21, 22, 23, 24, 25

I want it to be imported in 2 dimensional array. I wrote this code:

      INTEGER :: SMALL(10)      
      DO I = 1, 3
        READ(UNIT=10, FMT='(5I4)')    SMALL
        WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
      ENDDO

But it imports everything in one dimensional array.

EDIT:

I've updated code:

    program filet

    integer :: reason
    integer, dimension(2,5) :: small

    open(10, file='boundary.inp', access='sequential', status='old', FORM='FORMATTED')
    rewind(10)
      DO
        READ(UNIT=10, FMT='(5I4)', iostat=reason)    SMALL
        if (reason /= 0) exit
        WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
      ENDDO
      write (*,*) small(2,1)
    end program

Here is output:

        11  12  13  14  15
        21  22  23  24  25
          12
+1  A: 

Well, you have defined SMALL to be a 1-D array, and Fortran is just trying to be helpful. You should perhaps have defined SMALL like this;

integer, dimension(2,5) :: small

What happened when the read statement was executed was that the system ran out of edit descriptor (you specified 5 integers) before either SMALL was full or the end of the file was encountered. If I remember rightly Fortran will re-use the edit descriptor until either SMALL is full or the end-of-file is encountered. But this behaviour has been changed over the years, according to Fortran standards, and various compilers have implemented various non-standard features in this part of the language, so you may need to check your compiler's documentation or do some more experiments to figure out exactly what happens.

I think your code is also a bit peculiar in that you read from SMALL 3 times. Why ?

EDIT: OK, we're getting there. You have just discovered that Fortran stores arrays in column-major order. I believe that most other programming languages store them in row-major order. In other words, the first element of your array is small(1,1), the second (in memory) is small(2,1), the third is small(1,2) and so forth. I think that your read (and write) statements are not standard but widely implemented (which is not unusual in Fortran compilers). I may be wrong, it may be standard. Either way, the read statement is being interpreted to read the elements of small in column-major order. The first number read is put in small(1,1), the second in small(2,1), the third in small(1,2) and so on.

Your write statement makes use of the same feature; you might have discovered this for yourself if you had written out the elements in loops with the indices printed too.

The idiomatic Fortran way of reading an array and controlling the order in which elements are placed into the array, is to include an implied-do loop in the read statement, like this:

READ(UNIT=10, FMT='(5I4)', iostat=reason)  ((SMALL(row,col), col = 1,numCol), row=1,numRow)

You can also use this approach in write statements.

You should also study your compiler documentation carefully and determine how to switch on warnings for all non-standard features.

High Performance Mark
A: 

Adding to what High Performance Mark wrote...

If you want to use commas to separate the numbers, then you should use list-directed IO rather than formatted IO. (Sometimes this is called format-free IO, but that non-standard term is easy to confuse with binary IO). This is easier to use since you don't have to arrange the numbers precisely in columns and can separate them with spaces or commas. The read is simply "read (10, *) variables"

But sticking to formatted IO, here is some sample code:

program demo1

implicit none

integer, dimension (2,5) :: small

integer :: irow, jcol

open ( unit=10, file='boundary.txt', access='sequential', form='formatted' )

do irow=1, ubound (small, 1)
   read (10, '(5I4)')  (small (irow, jcol), jcol=1, ubound (small, 2))
end do

write (*, '( / "small (1,2) =", I2, " and small (2,1)=", I2 )' )  small (1,2), small (2,1)

end program demo1

Using the I4 formatted read, the data need to be in columns:

12341234123412341234
  11  12  13  14  15
  21  22  23  24  25

The data file shouldn't contain the first row "1234..." -- that is in the example to make the alignment required for the format 5I4 clear.

With my example program, there is an outer do loop for irow and an "implied do loop" as part of the read statement. You could also eliminate the outer do loop and use two implied do loops on the read statement, as High Performance Mark showed. In this case, if you kept the format specification (5I4), it would get reused to read the second line -- this is called format reversion. (On a more complicated format, one needs to read the rules to understand which part of the format is reused in format reversion.) This is standard, and has been so at least since FORTRAN 77 and probably FORTRAN IV. (Of course, the declarations and style of my example are Fortran 90).

I used "ubound" so that you neither have to carry around variables storing the dimensions of the array, nor use specific numeric values. The later method can cause problems if you later decide to change the dimension of the array -- then you have to hunt down all of the specific values (here 2 and 5) and change them.

There is no need for a rewind after an open statement.

M. S. B.