目的:创建一个程序,它接受两个单独的文件,打开并读取它们,将它们的内容分配给数组,对这些数组进行一些数学计算,创建一个带有产品编号的新数组,打印到一个新文件。够简单吧?
我的输入文件在开头有注释字符。一个问题是,它们是'#',它们是大多数绘图程序的注释字符,但不是FORTRAN。什么是告诉计算机不要查看这些字符的简单方法?由于我之前没有FORTRAN经验,我正在通过两个测试文件来完成这项工作。以下是我到目前为止的情况:
PROGRAM gain
IMPLICIT NONE
REAL, DIMENSION (1:4, 1:8) :: X, Y, Z
OPEN(1, FILE='test.out', &
STATUS='OLD', ACTION='READ') ! opens the first file
READ(1,*), X
OPEN(2, FILE='test2.out', &
STATUS='OLD', ACTION='READ') ! opens the second file
READ(2,*), Y
PRINT*, X, Y
Z = X*Y
! PRINT*, Z
OPEN(3, FILE='test3.out', STATUS='NEW', ACTION='WRITE') !creates a new file
WRITE(3,*), Z
CLOSE(1)
CLOSE(2)
CLOSE(3)
END PROGRAM
PS。请不要用一堆代码猴子gobblety gook压倒我。我是一个总编程新手。我不懂所有的术语,这就是为什么我来到这里而不是在现有网站上寻求帮助的原因。感谢。
答案 0 :(得分:6)
如果你的意思是注释只在文件的开头,那就很简单了 - 不需要计算注释行或倒带文件 - 你可以将这些行读成一个字符串并测试它们是否是一个评论。然后你最终会遇到一个非评论行。问题:它将被读入一个字符串,因此无法用于常规读取...解决方案...使用“退格”来读取一条记录,以便您现在可以使用普通文件读取来读取文件的其余部分。如果注释行穿插在整个文件中,则需要稍微复杂的解决方案 - 如前所述,将行读入字符串,然后从字符串中读取。
这是一个有用的例子......我假设“#”在第一列和各种其他简化假设中。一些建议:将子程序和函数放入模块并“使用”该模块 - 这将允许编译器检查接口。在开发程序时,尽可能多地使用代码检查和警告选项 - 特别是下标边界检查 - 最终会节省时间。
P.S。自Fortran 90以来它正式成为“Fortran” - 它是FORTRAN 77及更早版本的“FORTRAN”。
module read_file_module
implicit none
contains
subroutine read_file (UnitNum, FileName, NumRows, NumCols, Array )
integer, intent (in) :: UnitNum
character (len=*), intent (in) :: FileName
integer, intent (in) :: NumRows, NumCols
real, dimension (1:NumRows, 1:NumCols), intent (out) :: Array
character (len=300) :: line
integer :: i, j
open (unit=UnitNum, file=FileName, status='old', action='read' )
ReadComments: do
read (UnitNum, '(A)') line
if (line (1:1) /= "#") exit ReadComments
end do ReadComments
backspace (UnitNum)
do i=1, NumRows
read (UnitNum, *) (Array (i, j), j=1,NumCols)
end do
close (UnitNum)
return
end subroutine read_file
end module read_file_module
program test_prog
use read_file_module
implicit none
real, dimension (1:8, 1:4) :: Array
integer :: i, j
call read_file (66, 'TestFile.txt', 8, 4, Array)
do i=1, 8
write (*, '( 4(2X, F7.3) )' ) (Array (i, j), j=1,4)
end do
end program test_prog
一些测试数据显示输入数据的灵活性:
# comment one
# comment two
1.1 2.0 3.0 4.1
1.2 2.0 3.0 4.2
1.3 2.0 3.0 4.3
1.4
2.0 3.0 4.4
1.5 2.0 3.0 4.5
1.6 2.0 3.0 4.6
1.7 2.0 3.0 4.7
1.8 2.0 3.0 4.8
答案 1 :(得分:3)
编写一个子程序,将此逻辑放入一个位置,以便您可以为两个文件调用它。您需要将每行读作字符串并添加IF测试以检查给定行是否以“#”开头。如果该行以“#”开头,则只需阅读下一行。如果没有,请将字符串转换为值并将其添加到您要返回的值数组中。
答案 2 :(得分:1)
我对FORTRAN 77之外的任何事情都不熟悉,但这里有一些指针(以及你在答案中发布的工作版本)。首先是工作代码(我添加了行号):
1 REAL FUNCTION myfile(unit, file, rows, columns)
2 IMPLICIT NONE
3 INTEGER, INTENT(IN) :: unit, rows, columns
4 CHARACTER(LEN=*) :: file
5 REAL, DIMENSION (1:columns, 1:rows) ::X
6 OPEN(unit, FILE=file, STATUS='OLD', ACTION='READ')
7 READ(unit,*), X
8 PRINT*, X
9 CLOSE(unit)
10 myfile= 0
11 END FUNCTION myfile
12
13 PROGRAM gain
14 errno = myfile(1, "test.out", 8, 4)
15 END PROGRAM
区别在于:
您可以将myfile例程定义为子例程,而不是使用函数。在这种情况下,您肯定需要传入您想要填充的数组作为参数。您不需要第10行,而是将返回值分配给主程序中您将“调用”例程的变量。即第14行看起来像这样:
call myfile(1, "test.out",8,4)
编辑: 我发布了这个,然后意识到我忘了回答原来的问题。我这样做然后由于某种原因无法连接到SO上传编辑。所以他们终于来了。
这会让你的日常编译。要真正处理注释行,您有几个选项(至少这些是最初想到的)。这些是从最简单/最脆弱到更强大/一般的顺序:
您选择哪种方法(以及其他人可能有其他建议)取决于您的特定应用。祝你好运。