4

我做了一些虚拟代码来学习打开和读取文件。假设我有以下 test.dat 内容

1
2
3
4
5
6
7
8
9
10

我编写了以下代码来打开和读取数据文件

subroutine readdata
implicit none

integer             :: j
double precision    :: test

open(unit = 100, file = 'test.dat', status = 'old', action = 'read')
 do j = 1,  10
 read(100,*) test
 print *, 'N1=', test
end do

end subroutine

正如预期的那样,输出如下所示

 gfortran -g  -I/usr/include -o main main.o subroutines.o -L/usr/lib64/liblapack -L/usr/lib64/libblas
 test=   1.0000000000000000     
 test=   2.0000000000000000     
 test=   3.0000000000000000     
 test=   4.0000000000000000     
 test=   5.0000000000000000     
 test=   6.0000000000000000     
 test=   7.0000000000000000     
 test=   8.0000000000000000     
 test=   9.0000000000000000     
 test=   10.000000000000000     
 Main finished.

但是,如果数据存储在单行中,如下所示

1 2 3 4 5 6 7 8 9 10

那么上面的代码不能按预期工作。它只读取行中的第一个元素然后提示错误

sharwani@linux-h6qd:~/PHD_research/myCodes/data> ./runcase.sh
rm -f *.o *.mod *.MOD *.exe *.stackdump main
gfortran -g  -I/usr/include -c main.f90
gfortran -g  -I/usr/include -c subroutines.f90
gfortran -g  -I/usr/include -o main main.o subroutines.o -L/usr/lib64/liblapack -L/usr/lib64/libblas
test=   1.0000000000000000    
At line 9 of file subroutines.f90 (unit = 100, file = 'test.dat')
Fortran runtime error: End of file

所以,我的问题是我有一个数据文件,其中包含存储在单行中的 2879 (1 x 2879) 个数字。我将如何打开并读取数据文件中的所有这些数字?

4

2 回答 2

11

默认情况下,每个 Fortranread语句都读取一个值列表,然后前进到下一行的开头。可以将光标想象read为在输入文件中移动光标。所以你的陈述

read(100,*) test

当输入文件中的数字位于不同的行时,执行您期望的操作。当它们都在文件中的同一行时,第一个 read 语句读取一个值(即test)然后前进到下一行的开头以读取下一个值但没有下一行,并且您会收到运行时错误已经向我们展示了。

有2个简单的解决方案。

一,您可以在一个语句中从一行中读取多个值,例如,您可以声明

real, dimension(10) :: test

然后

read(100,*) test

应该一次性将所有值放入数组中。

其次,您可以使用输入,它告诉处理器在每条语句non-advancing之后不要跳到下一行的开头。read类似于以下内容(根据您的情况检查编辑描述符)

read(100,'(f8.2)',advance='no') test

如果您选择后一种方法,请不要忘记,在您读取了一行中的所有值之后,您确实想跳到下一行的开头,因此您可能需要执行如下语句

read(100,*)

它不会读取任何值,但会前进到下一行。

于 2013-10-17T09:00:15.463 回答
0

如前所述,您可以通过添加来连续读取数据

advance='no'

和正确的格式字符串(取决于您的数据;例如 'i2' 适用于 [1 2 3 4 5 6] 之类的数据表)到您的读取命令。另一个有用的技巧是通过在参数(即 io)上写入它的值并在没有运行时错误的情况下退出 do 循环来额外注意 I/O 状态,即使您不知道数据表的长度。例如,一个完整的程序可能如下所示:

program read
integer::a,io

open(100, file='data')
do
read(100,'(i2)',advance='no',IOSTAT=io)a
if (io<0) exit
if (io>0) stop 'problem reading'
write(*,*)a
end do

end program

玩得开心!

于 2013-10-17T20:36:02.087 回答