爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 25915|回复: 20

[求助] Fortran中显式循环和隐式循环

[复制链接]

新浪微博达人勋

发表于 2013-10-23 00:31:54 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
以前编程的时候遇到一个看似简单,但是很容易出错的问题,个人认为归结起来就是Fortran中do循环的显式写法和隐式写法。当时问了周围的一些同学都不知道为什么。最近又在给别人讲一些东西,所以就想起了这个问题。请大神出来答疑解惑,感激不尽!!!下面举个简单的例子:在D盘下有一个名为test.txt的文本文件,存储的是3×3的数据,详细内容如下1        2        34        5        6
7        8        9

下面我就分别用显式循环和隐式编写程序读取这个文件中的数据,然后直接输出到屏幕。(编译环境:VS2010+IVF11)
第一:显式循环
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas
integer i,j
open(1,file='D:\test.txt')
do i=1,row
   do j=1,col
      read(1,*) datas(i,j)
   enddo
enddo
print*,datas
end

编写完成之后,编译、链接、运行,在点击运行之后,就弹出一个错误提示:
forrtl: severe (24): end-of-file during read, unit 1, file D:\test.txt
Image              PC        Routine            Line        Source
Console1.exe       003DEDDA  Unknown               Unknown  Unknown
Console1.exe       003485AA  Unknown               Unknown  Unknown
Console1.exe       003477AB  Unknown               Unknown  Unknown
Console1.exe       0034BA28  Unknown               Unknown  Unknown
Console1.exe       0034122E  _MAIN__                    10  Source1.f90
Console1.exe       003E6213  Unknown               Unknown  Unknown
Console1.exe       003914F9  Unknown               Unknown  Unknown
Console1.exe       003913BF  Unknown               Unknown  Unknown
kernel32.dll       776AED5C  Unknown               Unknown  Unknown
ntdll.dll          777A37EB  Unknown               Unknown  Unknown
ntdll.dll          777A37BE  Unknown               Unknown  Unknown


第二:第一种隐式循环
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas
integer i,j
open(1,file='D:\test.txt')
do i=1,row
   read(1,*) (datas(i,j),j=1,col)
enddo
print*,datas
end


第二种隐式循环
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas
integer i,j
open(1,file='D:\test.txt')
read(1,*) ((datas(i,j),j=1,col),i=1,row)
print*,datas
end


上面两种隐式循环,编译、链接、运行都没有错误,能输出正确的结果。


密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2013-10-23 07:58:22 | 显示全部楼层
能看一下你的那个test.txt文件中数据的格式吗? 如果你的数据是一行一个数据,那么用第一种方法是可以读取的。如果是像你说的3*3 (三行 每行三列)的话那么第一种方法就不行了。因为如果一行三列数字的话read命令只能读取每行的第一个数字,其他的都忽略了。当整个嵌套循环到第四次的时候就已经遇到EOF了所以就出现了所错误。
如果非要用显式循环的话可以修改你的代码如下:
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas
integer i,j
open(1,file='D:\test.txt')
do i=1,row
   !do j=1,col
      read(1,*) datas(i,:)
   !enddo
enddo
print*,datas
end
密码修改失败请联系微信:mofangbao
回复 支持 2 反对 0

使用道具 举报

新浪微博达人勋

发表于 2013-10-23 08:21:54 | 显示全部楼层
再帮你补充一点,如果你的数据文件中是纯数据且已经知道响应的排列的话不需要用循环来读取数据,直接read就可以读取所有的数据到数组中。然后再通过其他函数调整数组中数据对应的排列。
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas,data_temp
integer i,j,stuts
open(1,file='D:\test.txt')
!do i=1,row
   !do j=1,col
      read(1,fmt=*,iostat=stuts) data_temp
     !if(stuts/=0) exit
   !enddo
!enddo
datas=transpose(data_temp)
print*,datas
end
这样的话比较消耗内存,建议用动态数组来分配内存。

评分

参与人数 2金钱 +16 贡献 +4 收起 理由
言深深 + 10 + 2 就是这个样子的!
lqouc + 6 + 2 说的很全面,给分

查看全部评分

密码修改失败请联系微信:mofangbao
回复 支持 2 反对 0

使用道具 举报

新浪微博达人勋

发表于 2013-10-23 07:32:13 | 显示全部楼层
@言深深赶紧来看看
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2013-10-23 08:05:29 | 显示全部楼层
另外,建议读取数据时在read函数中只用iostat 字段,以便监测读取是否发生错误。
program main
implicit none
integer,parameter::row=3,col=3
integer,dimension(row,col):: datas=10
integer i,j,stuts
open(1,file='D:\test.txt')
do i=1,row
   do j=1,col
      read(1,fmt=*,iostat=stuts) datas(i,j)
      if(stuts/=0) exit
   enddo
enddo
print*,datas
end
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2013-10-23 08:25:40 | 显示全部楼层
学习进步,多谢
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 成长值: 0
发表于 2013-10-23 09:08:36 | 显示全部楼层
建议学会用隐循环read数据,这样可以保证read在自己的掌控之下。
否则由于fortran的read规则和c不一样,如果直接用read(1,*) x,也能将数据read到数组x里面,但是行列顺利你就不知道了。
而且这时候数组x大小设置不一样,read出来的也不一样···具体可以自己测试测试就知道了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

0
早起挑战累计收入
发表于 2013-10-23 09:34:34 | 显示全部楼层
楼上几位基本都说了原因了,默认情况下,一次read对应一行数据
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2013-10-23 09:58:53 | 显示全部楼层
楼上都是大神啊,自己也遇到过这样的问题,确实显示循环只能读每一行的第一列数据,隐士循环就可以按行读取,记得fortran书上有的吧,楼主可以仔细找找
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2013-10-23 10:48:37 | 显示全部楼层

谢谢大神的详细讲解,受教了
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表