Pergunta

I am new to Fortran and i need to write a code that would allow me to read a text file(.dat) containing an array of data (1876 columns x 3126 rows) with irregular spaces/irregularly delimited and write it to a new file with consistent formatting. In short, i would just like the columns of the data be aligned with each other.

Ex:

 <4 spaces>    0.2341   15.0769
 <2 spaces>  -10.0672    1.6278    
 <3 spaces>   66.9851  -14.7123
 <3 spaces>   -0.4468   -2.5673

The above example is basically what the column of data should look like with the corresponding number of spaces before each value as indicated. The format of the values is 'f10.4'

Here's a code that i tried writing. I was able to compile the code and run the exe file, however, it failed to read from the text file and produced a runtime error: end of file.

program refgrid
implicit none

   integer :: nrow, ncol
   integer :: i, j
   real, dimension(:,:), allocatable :: mat

   print *, ' Input number of rows: '
   read *, nrow
   print *, 'Input number of columns: '
   read *, ncol

   allocate(mat(1:ncol,1:nrow))

   open(UNIT=1, FILE='bathymetry2.dat', FORM='FORMATTED', STATUS='OLD', ACTION='READ')

   do i=1, nrow
      read(UNIT=1, FMT=*) mat
   end do

   close(UNIT=1)

   open(UNIT=1, FILE='refgrid.dat', FORM='FORMATTED', STATUS='NEW', ACTION='WRITE')

   do i=1, nrow
      write(UNIT=1, FMT=101) mat
      101 format(1826f10.4)
   enddo

   close(UNIT=1)

end program refgrid

My questions:

  1. How can i read the values consecutively from a line using the do loop? I'm a bit confused in using the repetition feature of the f format in a 'do' loop.

  2. Can I read/write the array "mat" as a whole array? or How can I assign the data_list for read/write? Can I assign the whole matrix instead of the individual elements?

I would greatly appreciate any help on this matter. Thank you!

Foi útil?

Solução

The problem is, that at every iteration in your do loop you try to read in as many elements as you have in the entire array mat. You should fill only one column in each iteration. Alternatively, you can read in the entire array with one read statement without any loops.

As for the writing, you need to repeat the format as many times as you have columns. I'd suggest to create a format string dynamically, so that it is automatically adapted to the number of columns entered by the user. See the example below. You can omit the do loop for the writing as well, as Fortran will automatically add an end of record sign (a newline), when all format specification had been consumed, and it will start to apply them again.

program refgrid
  implicit none

  integer :: nrow, ncol
  real, allocatable :: mat(:,:)
  character(20) :: form

  print *, ' Input number of rows: '
  read *, nrow
  print *, 'Input number of columns: '
  read *, ncol

  allocate(mat(1:ncol, 1:nrow))
  open(unit=1, file='bathymetry2.dat', status='OLD', action='READ')
  read(1, *) mat
  close(1)

  write(form, "(A,I0,A)") "(", ncol, "F10.4)"
  open(1, file='refgrid.dat', form='FORMATTED', status='NEW', action='WRITE')
  write(1, form) mat
  close(1)

end program refgrid

UPDATE: As for the dynamic creation of the format specifier: You write into the string form three things: a string (A), an integer with only as many characters as it requires (I0) and an other string (A). The first string is (, the integer is ncol and the second string is F10.4). So, provided ncol had the value 128, you will have in form the string (128F10.4). This is a string containing a valid format specifier, so you can use it in your write statement instead of a hard coded format specifier.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top