Fortran如何读取打印文件变量 适配可变行列数数据文件
Fortran 可变行列数文本文件读写修复方案
原代码核心问题
- 未添加
implicit none声明,遵循Fortran默认隐式类型规则,且未显式声明数组A的类型,同时定义了Var1~Var14共14个完全未使用的字符数组,属于无效代码。 - 使用Fortran内置函数名
len作为常量名,容易引发命名冲突和语法错误。 - 完全缺失文件读取逻辑,打开文件后直接输出未初始化的数组
A,访问未初始化内存是程序崩溃的核心原因。 - 硬编码行数644、列数14,无法适配行列数不固定的输入场景。
- 第二个循环使用了从未定义赋值的变量
ip,访问未初始化值会触发内存越界崩溃。 - 未处理文件首行的字符串表头,直接按数值读取会触发类型不匹配的读取错误。
- 固定格式续行语法错误,定义字符变量的第二行续行前多写了一个逗号。
- 输出格式硬编码为
f3.1,会截断输入中长度超过该格式的浮点数(比如样例中40.548这类长度的数值)。
适配任意行列数的正确实现
Fortran 90及以上版本支持动态内存分配,不需要提前用parameter、dimension写死数组维度,可以先扫描文件获取实际行列数,再分配数组完成读写,可运行代码如下:
program read_flexible_data implicit none real, allocatable :: data(:,:) ! 动态数组,存储所有数值数据 integer :: nrows, ncols ! 实际有效数据行数、列数 integer :: i, io_stat, file_id character(len=1024) :: line_buf, header ! 第一步:打开文件,读取表头统计列数 open(newunit=file_id, file='testdata.txt', status='old', action='read') read(file_id, '(a)', iostat=io_stat) header if (io_stat /= 0) error stop '文件为空或无读取权限' ncols = count_split_cols(header) print *, '检测到文件列数:', ncols ! 第二步:遍历文件统计有效数据行数 nrows = 0 do read(file_id, '(a)', iostat=io_stat) line_buf if (io_stat /= 0) exit if (len_trim(line_buf) == 0) cycle ! 跳过空行 nrows = nrows + 1 end do print *, '检测到有效数据行数:', nrows ! 第三步:分配数组内存,回到文件起始位置读取数据 allocate(data(nrows, ncols)) rewind(file_id) read(file_id, '(a)') header ! 跳过表头行 do i = 1, nrows read(file_id, *) data(i,:) ! 自由格式读取,适配空格分隔的任意长度数值 end do close(file_id) ! 第四步:输出验证,写入结果文件并打印第一列到控制台 open(newunit=file_id, file='EX-1.out', status='replace', action='write') write(file_id, '(a)') trim(header) do i = 1, nrows write(file_id, '(*(g0,1x))') data(i,:) ! g0格式自动适配数值长度,1x为列间空格 write(*, '(g0)') data(i,1) end do close(file_id) deallocate(data) contains ! 内部子程序:统计空格分隔的字符串列数 integer function count_split_cols(s) character(len=*), intent(in) :: s integer :: pos logical :: in_token count_split_cols = 0 in_token = .false. do pos = 1, len_trim(s) if (s(pos:pos) /= ' ' .and. .not. in_token) then count_split_cols = count_split_cols + 1 in_token = .true. else if (s(pos:pos) == ' ') then in_token = .false. end if end do end function count_split_cols end program read_flexible_data
关键语法说明
- 动态数组使用:声明数组时添加
allocatable属性,不需要提前固定维度,扫描文件得到实际行列数后用allocate(数组名(行数,列数))分配内存即可,使用完成后用deallocate释放内存,可适配任意大小的空格分隔数值文件。 - 文件操作:推荐使用
newunit参数自动分配未被占用的文件通道号,避免手动写7、8这类固定通道号引发的占用冲突。 - 读取规则:空格分隔的数值文件直接用
read(通道号, *)的自由格式读取即可,不需要硬编码固定format,避免数值长度不匹配触发读取错误。 - 输出规则:通用数值输出使用
g0格式描述符,可以自动适配整数、浮点数的输出长度,不会出现固定f格式截断数值的问题。 - 所有代码开头必须加
implicit none,关闭Fortran默认的隐式类型规则,避免未声明变量引发的未定义行为。
内容的提问来源于stack exchange,提问作者Ivan Mich
相关产品推荐
相关产品推荐

