Fortran Coder

查看: 144|回复: 10

[文件读写] 新手学习fortran,调试时read会莫名触发断点。

[复制链接]

5

帖子

1

主题

0

精华

新人

F 币
28 元
贡献
11 点
发表于 2022-7-17 13:53:29 | 显示全部楼层 |阅读模式
各位前辈大佬、同学们好!我接触学习fortran、折腾代码好几天了就是解决不了问题,无奈向大家求助!如果发帖格式或者内容有什么不对,请管理员和大家指正!

1. 我目前在笔记本上测试代码,用的是Intel Parallel Studio XE 2013 with VS2012(同学以前帮我安装的,应该是破解版)。生成解决方案没问题、触发断点返回后显示各种dll文件已加载。
2. 我在学习、测试同行前辈给的fortran代码,看起来似乎是以77为基调写的。

我碰到的问题是:在open一个外部的mask.dat数据文件后,无法有效的read,总是会触发断点

我的学习、调试经历和心路历程如下:
(1)最初是用77的格式.for建了一个代码,尝试读取mask.dat文件,里面就是321行681列的0和1,作为网格供后续使用。在触发断点之后,我一开始想会不会我弄错了行数和列数,于是我分别测试了im=681,jm=321以及im=321,jm=681。还是会在read是触发断点。

(2)于是我简化问题,做了个test.dat:2行2列的矩阵[1 2;3 4]。但read时候还是断点。

(3)之后我也百度了如何用循环读取数据,也解决不了问题(见图1)。百度经验如下:
open(100,file='test.dat',form='formatted')      

do i=1,2
read(100,*) (ismask(i,j),j=1,2)
end do
close (100)

(4)我开始怀疑是不是read本身有问题,甚至怀疑会不会是parallel和vs安装时出问题而没注意到?因为在调用堆栈里的信息总是提到“未知函数”。但是我无意中看到了论坛里的一篇文章:教你看懂intel fortran的运行时错误(教你看懂 Intel Fortran 的运行时错误 - Fortran教程 - Fortran Coder 程序员聚集地 (fcode.cn)),文章说道:“由源代码 11 行可知,此处使用了 read(*,*) i 语句,这便是上面第7和第8步骤里的未知函数。read 在源代码里虽然是一个语法规定的语句,但编译后,则是一个函数(位于运行时库中),我们无法看到 read 的源代码。” 看完后我懵懵懂懂,但是有了一点信心再试试,应该是新手的我没有做对。

(5)我想会不会抛弃77、新建一个.f90可以解决问题,但还是会触发断点。(见图2)

(6)测试发现键盘输入是可行的(见图3),但是我不能回避问题。一方面键盘输入mask的600*300的网格就已经很劝退了,另一方面后续还有几个别的文件要读取,是100*100*100级别的。


(7)会有可能是因为我把源码和数据文件放在source和resource里不妥当么?(见图4)


我以前都是用matlab处理数据+可视化的,现在刚接触fortran要学习搭建模型、制作数据,是真的很小白。目前非常茫然、非常期望能得到有经验的大佬们的指点、帮助!哪怕是指点我要不要卸载了重新安装软件?

图4

图4

图3

图3

图2

图2

图1

图1

评分

参与人数 1F 币 +5 收起 理由
fcode + 5 求助贴榜样

查看全部评分

170

帖子

2

主题

0

精华

宗师

F 币
1648 元
贡献
792 点

规矩勋章

发表于 2022-7-17 23:30:57 | 显示全部楼层
我觉得可能是变量定义的问题。Fortran程序中所有的变量必须在程序开始被定义。I 和 J 都没有定义(包括im,  jm),他们的数值很可能是乱码,运行结果不可预知。

30

帖子

0

主题

0

精华

专家

F 币
566 元
贡献
174 点

元老勋章新人勋章

QQ
发表于 2022-7-18 08:17:47 | 显示全部楼层
1. 发帖不需要什么特别的格式,说清楚就行。
2. 遇到断点,优先查看命令行窗口(通常是黑色窗口)的错误提示。
3. 请给出你 test.dat 文件的内容。(1,2,3,4的排布)
4. 和 .f90 或 .for 扩展名无关。它只影响是自由格式还是固定格式。(甚至都不影响是F77还是F90)
5. 你不需要把 .dat 文件放在 Resource Files 里面。(当然放了也没关系)

综合来说,我觉得是你的 .dat 文件内容不对。或者是路径不对。

38

帖子

3

主题

0

精华

熟手

F 币
154 元
贡献
77 点
发表于 2022-7-18 19:41:01 | 显示全部楼层
本帖最后由 zjk0112 于 2022-7-18 20:15 编辑

你那个read(100) 这里就有问题,应该是read(100,*) 100 表示通道号,*表示默认格式。默认read是按行顺序读取,read(100,*) m,n,nnz 表读取文件第一行的前三个值,这三个值分别按顺序存放在m,n,nnz中。如果你有100行就加一个do i=100的循环。        你试试open后面不用form那个参数。我一般就open(100,file='test.dat') 或者open(100,file='test.dat',status='old')
image-20220718193716736.png

38

帖子

3

主题

0

精华

熟手

F 币
154 元
贡献
77 点
发表于 2022-7-18 20:01:40 | 显示全部楼层
zjk0112 发表于 2022-7-18 19:41
你那个read(100) 这里就有问题,应该是read(100,*) 100 表示通道号,*表示默认格式。你试试open后面不用for ...

那个read(*,*)也是不对的用法。另外,楼主很不错,即主动有勤快,会主动注释排查错误,比很多往网上一挂等答案的强多了。至于不清楚问题的根源,还能把这么多信息和心路历程发出来,并且把错误排查在read的用法上,这里就很值得点赞。

38

帖子

3

主题

0

精华

熟手

F 币
154 元
贡献
77 点
发表于 2022-7-18 20:08:26 | 显示全部楼层
I和J乱码是因为没有初始化。就是要给出初值,否则它的是随机的。比如,在Fortran中声明   integer:: i.此时和MATlab的区别是i并不是0,你需要给 i 赋值  ,像这样i=0.

5

帖子

1

主题

0

精华

新人

F 币
28 元
贡献
11 点
 楼主| 发表于 2022-7-18 20:21:18 | 显示全部楼层
风平老涡 发表于 2022-7-17 23:30
我觉得可能是变量定义的问题。Fortran程序中所有的变量必须在程序开始被定义。I 和 J 都没有定义(包括im, ...

谢谢您的建议!我的问题找到了,是我这边读取外部文件的路径没有设置好,另外还需要配合read(标号,*)的形式。不过您提到的i和j没有提前声明,我很重视,也测试了一下。因为我注意到前辈给我的代码里就有读取mask之后做小循环把mask里里面数值是1的那些格点按照公式计算成新的系数,但是循环里的i和j就没有在代码开头声明。结果证明:不提前声明i和j也是可以运行的(用于循环的小范围的即时的不需要?)。但其实我也不明白这是为什么,希望日后能学习到,或者如果有知道的大佬还请不吝赐教!总之,我还是非常感谢您的经验和指点意见,祝您生活愉快!

5

帖子

1

主题

0

精华

新人

F 币
28 元
贡献
11 点
 楼主| 发表于 2022-7-18 20:29:23 | 显示全部楼层
布衣龙共 发表于 2022-7-18 08:17
1. 发帖不需要什么特别的格式,说清楚就行。
2. 遇到断点,优先查看命令行窗口(通常是黑色窗口)的错误提 ...

谢谢您的建议!我的问题找到了,是我这边读取外部文件的路径没有设置好,另外还需要配合read(标号,*)的形式。
您给的建议,检查数据文件的路径,非常关键!当我把读取文件的代码行从open(标号,file='test.dat')改成了open(标号,file='D:\...\test.dat')这种格式后,就成功运行了!我之前以为把数据文件放到resource里面就可以略去之前的文件夹名,是我的锅。
另外,我注意到VS里面关于resource里的数据文件的显示是似乎滞后的。我把数据文件移动到新的文件夹后,再去点解决方案资源管理器的那个数据文件,显示的地址还是移动前的地址!有点无语。
总之,我非常您的经验和指点意见,祝您生活愉快!

5

帖子

1

主题

0

精华

新人

F 币
28 元
贡献
11 点
 楼主| 发表于 2022-7-18 20:35:34 | 显示全部楼层
zjk0112 发表于 2022-7-18 19:41
你那个read(100) 这里就有问题,应该是read(100,*) 100 表示通道号,*表示默认格式。默认read是按行顺序读 ...

谢谢您的建议!我的问题找到了,是我这边读取外部文件的路径没有设置好,另外还需要配合read(标号,*)的形式。
我修改代码试了好几次,发现如您所说,read(标号,*)是保障成功运行的关键!当我按照另一位高手所说的修改了路径之后,发现只用read(100)是不行的。此外,我测试了open行,我这边结果是无论open行里有没有form、有没有status都不影响结果。
总之,我非常感谢您的经验和指点意见,祝您生活愉快!

5

帖子

1

主题

0

精华

新人

F 币
28 元
贡献
11 点
 楼主| 发表于 2022-7-18 20:52:42 | 显示全部楼层
zjk0112 发表于 2022-7-18 20:08
I和J乱码是因为没有初始化。就是要给出初值,否则它的是随机的。比如,在Fortran中声明   integer:: i.此时 ...

抱歉,我20点左右刚看到您们的回复就去测试了(白天在学习专业知识,没有看论坛),当时只看到您的第一条回复,没看到您的这条回复。
我就说为啥一开始虽然也是触发断点,但是看“局部变量”那里,显示i=1,j=8...balabala。提前声明integer::i可以防止报错(可能别的同学会遇到)。
您说的这个提前也可以给i声明一下确实一针见血!其实我在做Matlab循环前,也会在for循环前加一句output=[];或者output=zeros(i, j)*nan;不然matlab经常会报错数据不匹配(等式右边算出来的矩阵不能赋给一个毫无定义的或者维度不对的output)
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2022-8-11 07:32

Powered by Tencent X3.4

© 2013-2022 Tencent

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