Fortran:从文本文件读取和打印2D数组 [英] Fortran: Reading and printing 2D array from text file

查看:62
本文介绍了Fortran:从文本文件读取和打印2D数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试读取3x3数组并将其打印出来,但出现行尾错误:

I am trying to read a 3x3 array and print it out but I am getting an end of line error:

文本文件包含以下数组:

The text file contains the following array:

1 2 3
4 5 6
7 8 9

这是我的代码:

program myfile
implicit none 

! Declare Variables
integer i,j
!real, dimension(1:3,1:3) :: A
integer, parameter :: M = 3, N =3
real, dimension(1:M,1:N) :: A

! Open and read data
open(unit=10, file = 'test_file_cols.txt', status = 'old')
do i =1,M
    do j =1,N
        read(unit=10,FMT=*) A(i,j)
        print *,A(i,j)
    end do
end do      

end program myfile

我得到的错误如下:

   1.000000
   4.000000
   7.000000
forrtl: severe (24): end-of-file during read, unit 10, file C:\Users\M42141\Documents\mean_flow_file\test_file_cols.txt

推荐答案

如默认情况下在注释中简要讨论的那样,Fortran中的所有I/O都是基于记录的.对于格式化和未格式化的文件都是如此.发生的情况是该文件被视为一组记录-您可以将一条记录视为文件中的一行.现在这些行可能非常长,特别是在未格式化的文件中,但是默认的Fortran I/O方法仍将其视为一组行.

As discussed briefly in the comments by default all I/O in Fortran is record based. This is true for both formatted and unformatted files. What happens is the file is viewed as a set of records - and you can think of a record as a line in the file. Now these lines may be very, very long, especially in an unformatted files, but the default Fortran I/O methodology still views it as a set of lines.

现在重要的是,默认情况下,每次执行I/O语句(读,写,打印)时,它所做的最后一件事就是从其上的记录移至下一条记录-一条写语句将写入记录结束标记.这就是为什么您在write语句之后自动获得换行符的原因,但是这也意味着对于read语句,记录(在线)上的所有剩余数据都将被跳过.这就是您正在发生的事情.第一次读取将读取记录1,因此您将获得1.0,然后移至记录2.您的程序随后将读取记录2,因此您将获得4.0,然后它自动移至记录3.然后将其读取(9.0)和文件指针移到记录4上.然后尝试读取该记录,但没有记录4,因此遇到了文件结束错误.

Now the important thing is that by default every time you perform an I/O statement (read, write, print) the last thing it does is move from the record it is on to the next record - a write statement will write an end of record marker. This is why you automatically get a newline after a write statement, but it also means that for a read statement any remaining data in the record (on the line) will get skipped over. This is what is happening to you. The first read reads record 1, and so you get 1.0, and then moves to record 2. Your program then reads record 2 and so you get 4.0, and it automatically moves to record 3. this is then read (9.0) and the file pointer moves onto record 4. You then try to read this, but there isn't a record 4, so you get an end of file error.

当您初次遇到记录结构时,它有点奇怪,但是当您习惯它时,它是非常强大且方便的-我将在下面显示一个示例,另一个可能是您可以在该结构上留下评论每行的末尾说明了它的作用,read语句的末尾将意味着您移至下一条记录,因此跳过注释,并且无需在代码中采取任何特殊操作即可处理这种情况.

Record structure is a bit strange when you first encounter it, but when you get used to it it is very powerful and convenient - I'll show an example below, and another one might be that you could leave a comment at the end of each line saying what it does, the end of the read statement will mean you move to the next record, so skipping the comment and needing to take no special action in you code to deal with such a case.

无论如何如何解决您的案件.三种可能的方式

Anyway how to solve your case. Three possible ways

  1. 一次读取整条记录-注释暗示了一个隐式的do循环,但我认为在这种情况下,数组部分更容易,更直观
  2. 您可以一次性读取整个数组.之所以可行,是因为当一条read语句完成一条记录并发现它仍然需要"更多数据时,它将携带到下一条记录中并继续读取.但是请注意,行尾注释的想法在这里不起作用-您能找出原因吗?
  3. 非高级I/O.在这种情况下,我完全不建议这样做,但是为了完整起见,这使您可以执行读取或写入操作而无需移至下一条记录

可能还有其他人,您可能会使用所谓的流I/O,但就个人而言,我更喜欢基于记录的记录,我发现它更方便,功能更强大.无论如何,这里是一个说明这三种方法的程序.请注意,我也更改了您的输入文件,使原始文件可以与非高级I/O一起使用很麻烦,但其他2则不行-另一个原因是此处不使用它.

There may be others, you could probably use so called stream I/O but personally I prefer record based whenever possible, I find it more convenient and powerful. Anyway here is a program illustrating the 3 methods. Note I have also changed your input file, getting the original to work with non-advancing I/O is a pain, but not the other 2 - another reason not to use it here.

ian @ eris:〜/work/stack $ cat readit.f90

ian@eris:~/work/stack$ cat readit.f90

Program readit

  Implicit None

  Real, Dimension( 1:3, 1:3 ) :: a

  Integer :: i, j

  ! one line per read
  Write( *, * ) 'Line at a time'
  Open( 10, file = 'in' )
  Do i = 1, 3
     Read ( 10, * ) a( i, : )
     Write(  *, * ) a( i, : )
  End Do
  Close( 10 )

  ! All in one go
  Write( *, * ) 'All in one go'
  Open( 10, file = 'in' )
  Read ( 10, * ) a
  Write(  *, * ) a
  Close( 10 )

  ! Non advancing I/O
  Write( *, * ) 'Non-advancing'
  Open( 10, file = 'in' )
  Do i = 1, 3
     Do j = 1, 3
        ! Non advancing I/O requires a 'proper' format
        Read ( 10, '( f3.1, 1x )', Advance = 'No' ) a( i, j )
        Write(  *, '( f3.1, 1x )', Advance = 'No' ) a( i, j )
     End Do
     ! Move to next records (lines)
     Read ( 10, * )
     Write(  *, * )
  End Do
  Close( 10 )

End Program readit
ian@eris:~/work/stack$ gfortran-8 -Wall -Wextra -pedantic -std=f2008 -fcheck=all -O readit.f90
ian@eris:~/work/stack$ cat in
1.0 2.0 3.00 
4.0 5.0 6.00 
7.0 8.0 9.00 

ian@eris:~/work/stack$ ./a.out
 Line at a time
   1.00000000       2.00000000       3.00000000    
   4.00000000       5.00000000       6.00000000    
   7.00000000       8.00000000       9.00000000    
 All in one go
   1.00000000       2.00000000       3.00000000       4.00000000       5.00000000       6.00000000       7.00000000       8.00000000       9.00000000    
 Non-advancing
1.0 2.0 3.0 
4.0 5.0 6.0 
7.0 8.0 9.0 

这篇关于Fortran:从文本文件读取和打印2D数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆