我有一个ASCII格式的数据(.txt文件),其中日期是以一年一格(即.9900601)的格式列中给出的。我想将此列分为三列,每列包含年,月和日期。谁能告诉你如何在Fortran中做到这一点?我的数据文件和代码如下:
数据表
19480501 -1
19480502 -1
19480503 2
19480504 -1
19480505 2
19480506 -1
19480507 -1
19480508 -1
19480509 -1
19480510 -1
19480511 -1
19480512 2
。 。
。
代码:
program ascii_read
!real(kind=8):: rain(np)
real,allocatable:: rain(:)
integer::np=15739
!integer(kind=8)::day(np)
integer,allocatable::day(:)
character(len = 80)::firstline
integer::i,j
integer,allocatable:: year(:)
allocate (year(np-1))
allocate (rain(np))
allocate (day(np))
open(1243,file="11700.text",status="unknown")
open(12,file="11700_output.text",status="unknown")
read(1243,*)firstline
do i=2,np
read(1243,1111)day(i),rain(i)
end do
1111 Format(i6,F5.2)
write(*,*)day
do j = 1,np-1
year(j)=day(j)
end do
write(*,fmt='(i4)')year
1 format(I4)
!write(*,*)year
return
stop
end program
这使得一年中只有一年分开,而不是一个月和一天。知道如何将月份和日期与此数据文件分开吗?
答案 0 :(得分:3)
您可以使用格式化的读取来明确地提取每个字段:
integer year,month,day,rain
...
read(1234,'(i4,i2,i2,i3)')year,month,day,rain
在您的代码中,您使用i6
,因此day(i)
包含“194805”之类的内容,然后从该行的其余部分读取rain(i)
(即“{1}}的最后两位数字” date“整数空格和另一个整数”。我不知道f5.2
格式对此做了什么,但它不是你想要的那样)
答案 1 :(得分:2)
您必须分析输入和所需输出之间的关系,然后实现关系;这就是编程的工作原理。你必须首先知道一种方法来自己解决问题,然后教电脑如何做到这一点。
对于这个问题,你可以简单地看到前4位代表年份,接下来的2位代表月份,最后2位代表日期。要获得前4个,您将整数除以10000,它只是拒绝最后4个(月和日)。您使用模运算来获取最后四个。并做同样的事情来提取最后两个月的月份。
定义新的数组变量month
和date
并将它们分配到与day
相同的大小,同时添加一个新的整数变量tmp并将第二个循环更改为:
do j = 1,np-1
year(j)=day(j)/10000
tmp = mod(day(j), 10000)
month(j) = tmp/100
date(j) = mod(tmp,100)
end do
我还建议您使用免费格式阅读。您可以使用固定格式进行写入以对齐数据并使其易于可视化。
开始时去寻找现代编程。在代码中,Litteral数字不是一个好主意,因此对文件ID使用命名常量。确保在不再需要文件时关闭文件。当您打开文件进行阅读时,请使用status ='old',您希望文件存在,或者您希望程序停止并显示相应的消息。使用格式时,请使用格式参数read
和write
而不是格式语句,例如使用名称arg fmt
,就像在某些地方一样。这使调试变得容易。所以你的程序看起来像这样。
program ascii_read
!real(kind=8):: rain(np)
integer, parameter :: inputId = 1243
integer, parameter :: outputId = 12
real,allocatable,dimension(:):: rain
integer::np=12
!integer(kind=8)::day(np)
character(len = 80)::firstline
integer::i,j, tmp
integer,allocatable,dimension(:):: day, year, month, date
allocate ( year(np-1), rain(np), day(np), month(np), date(np) )
open(inputId,file="11700.text",status="old")
open(outputId,file="11700_output.text",status="unknown")
read(inputId,*)firstline
do i=2,np
read(inputId,*)day(i),rain(i)
end do
close(inputId)
write(*,*) day
do j = 1,np-1
year(j)=day(j)/10000
tmp = mod(day(j), 10000)
month(j) = tmp/100
date(j) = mod(tmp,100)
! just to see what we get.
write(*, *) day(j), year(j), month(j), date(j)
end do
!write(*,fmt='(i4)')year
!1 format(I4)
!write(*,*)year
return
stop
end program
感谢IanH的评论,最新版本的fortran包含了一个newunit选项,用于处理程序员的IO单元号。这使您无需为单元号定义命名常量。如果您不使用最新版本(有些公司不经常升级),可以在fortranwiki中使用。
答案 2 :(得分:1)
A" hybrid"另外两个答案的方法是首先将数据读入缓冲区,然后将其拆分为整数
collection-repeat
这里,列表导向的I / O用于在第一列之前跳过可能的空格,而整数则根据宽度提取。此外,注释行以"#"开头。例如,在第一个读取语句之后插入collection-repeat
可以跳过(如果有的话)。