2

I want to read matrix A of dimension(n,n) from a input file, n is a variable and n<=50. For testing I took an example matrix as:

5.0   6.0   7.0
4.0   3.0    8.0
1.0   4.0    2.0

I want to read it in same format element-wise using the below code:
But when I compiled it I was getting error:

At line 15 of file partial_pivot.f90 (unit = 9, file = 'gaussj.inp') Fortran runtime error: End of file.

How this problem can be resolved?

program gaussj
implicit none
integer::i,j,n
integer,parameter::nmax=50
real,dimension(nmax,nmax)::A


 open(unit=9,file='gaussj.inp',status='old')
 n = 0
 do i = 1,nmax
   n = n+1

   read(9,*)(A(i,j),j = 1,nmax)


 end do
 close(9)

 write(25,*)((A(i,j),j=1,n),i=1,n)
end program
5
  • How big is the matrix in the file? Is it really 50x50 or is it smaller? nmax must correspond to the size of the matrix. Commented Mar 22, 2018 at 12:08
  • you can simply do read(9,*)a (no loops), then transpose(a) if needed Commented Mar 22, 2018 at 12:13
  • 6
    Do yourself a favour and write the dimensions of the array into the first line of the file. Then you can read the dimensions, allocate the arrays and read them. Commented Mar 22, 2018 at 12:18
  • @agentp, that's still going to try to read 2500 elements from a file providing 9. Commented Mar 22, 2018 at 12:46
  • oh I misread, I thought he knew the dimension was 50x50 if you do not know a priori the number of values on a line it becomes rather cumbersome.. see for example stackoverflow.com/q/10661901/1004168 ( of course putting the dimension in the file makes life much simpler ) Commented Mar 22, 2018 at 13:26

2 Answers 2

1

in this case if you want to assume its a square array, (and there is nothing else in the file) you can get the dimension by counting lines..

  implicit none
  integer i,n,stat
  real x
  real,allocatable::a(:,:)
  open(20,file='test.dat')
  n=-1
  stat=0
  do while(stat == 0)
     n=n+1
     read(20,*,iostat=stat)x
  enddo
  write(*,*)n
  allocate(a(n,n))
  rewind(20)
  read(20,*)a
  a=transpose(a)
  do i=1,n
     write(*,*)A(i,:)
  enddo
  end
Sign up to request clarification or add additional context in comments.

Comments

0

Not the fastest way, but working for small matrices in GFortran. This solution is given for rectangular integer matrices, but I guess it can be easily transformed for real matrices as it was in the question. I'm a newbie in coding, so any improvements would be welcome.

  Program Example
  Implicit none

  Integer, allocatable, dimension(:,:) :: A
  Integer :: M, N ! numbers of rows and columns of the input matrix
  Integer :: i

  Character(len=20) :: FMT ! variable format for rows of the matrix
  
  Open(1, FILE='In.txt')  ! file with the input matrix
  Open(2, FILE='Out.txt') ! file for its copy

  Call ReadArray(A, M, N)

  Write(FMT,"( '(',I0,'(I4))') ") N

  Write(2,*) 'Input matrix:'
  Write(2,FMT)(A(i,:),i=1,M)

  Deallocate(A)

  CONTAINS
  
  Subroutine ReadArray(Array, M, N)

        Integer, intent(out), Allocatable, Dimension(:,:) :: Array
        Integer, intent(out) :: M, N ! matrix dimensions
        
        Integer, Allocatable, Dimension(:,:) :: T ! temporary matrix
        Integer, Allocatable, dimension(:) :: RV ! current row vector
        Character*100 s       ! processed line from the input file
        Character :: d = ' '  ! delimiter
        Integer stat, p, q, r           
      
        M = 0  ! number of rows
        N = 0  ! number of columns
        stat=0

        Do while(.TRUE.)
              Read (1, '(a)', iostat=stat) s
              if (stat /= 0) exit
              M = M + 1
        
              If (N==0) then ! determine number of columns
                    p = 1
                    Do
                          q = verify( s(p:), d) ! position of a first non-delimiting symbol
                          if (q == 0) exit
                          r = scan( s(p+q:), d) ! length of the current number                 
                          N = N + 1                  
                          p = p + (q-1) + (r-1) + 1
                    End Do

                    Allocate( RV(1:N) )                        
              End if

              Read(s,*) RV(1:N)                 

              If (M==1) then
                    Allocate (Array(M,N))
              Else
                    Deallocate( Array )
                    Allocate( Array(M,N) )
                    Array(:M-1,:) = T                        
                    Deallocate( T )                   
              End if

              Array(M,:) = RV
              Allocate( T(M,N) )
              T(:,:) = Array                
        End Do

        Deallocate( RV, T )

  End Subroutine ReadArray
  
  End Program Example

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.