如何在Fortran中读取文本文件第二列并分配到可分配数组?
Fortran提取文本文件第二列到可分配数组的正确实现
问题说明
你需要从包含两列实数的文本文件中提取第二列数据,存入可分配数组,但目前的实现方式报错,下面给出两种可靠的解决方法。
先明确你可能遇到的典型错误场景:
示例文本文件(data.txt)
1.2 3.4 5.6 7.8 9.0 1.1 2.2 3.3
你可能写的错误代码
program read_col implicit none real, allocatable :: arr(:) integer :: i, n open(10, file='data.txt') read(10, *) (arr(i), i=1,n) ! 错误:数组未分配就直接写入 close(10) end program read_col
对应的报错
Error: Allocatable array 'arr' is not allocated at (1)
方法一:先统计行数再分配数组(高效稳定)
这种方法需要先读取一次文件统计总行数,再分配对应大小的数组,最后重新读取提取第二列,适合大多数场景。
program extract_second_col implicit none real, allocatable :: second_col(:) integer :: file_unit, line_count, i, stat real :: dummy ! 用来承接第一列的无用数据 ! 打开文件,用newunit自动分配安全的单元号 open(newunit=file_unit, file='data.txt', status='old', action='read', iostat=stat) if (stat /= 0) then print *, '打不开文件,请检查路径是否正确' stop end if ! 第一步:统计文件的行数 line_count = 0 do ! 读取一行的两个数,只计数不保存 read(file_unit, *, iostat=stat) dummy, dummy if (stat /= 0) exit ! 读到文件末尾或出错时退出循环 line_count = line_count + 1 end do rewind(file_unit) ! 将文件指针移回开头,准备重新读取 ! 第二步:根据行数分配数组 allocate(second_col(line_count), stat=stat) if (stat /= 0) then print *, '数组分配失败,内存不足?' close(file_unit) stop end if ! 第三步:读取每一行的第二列数据 do i = 1, line_count read(file_unit, *) dummy, second_col(i) ! 跳过第一列,存第二列 end do close(file_unit) ! 验证输出(可选) print *, '提取的第二列数据:' do i = 1, line_count print *, second_col(i) end do end program extract_second_col
关键细节说明
- 用
newunit代替硬编码的单元号(比如10),避免和其他代码的单元号冲突 - 加入
iostat检查文件操作和数组分配的错误,让程序更健壮 rewind命令用于重置文件指针到开头,这样不需要重新打开文件
方法二:动态扩展数组(无需提前统计行数)
如果不想两次读取文件,可以每次读取一行就动态扩展数组的大小,适合不确定文件行数的场景(小文件效率影响不大)。
program dynamic_extract_col implicit none real, allocatable :: second_col(:) integer :: file_unit, current_size, i, stat real :: dummy, col_val open(newunit=file_unit, file='data.txt', status='old', action='read', iostat=stat) if (stat /= 0) then print *, '文件打开失败' stop end if current_size = 0 do read(file_unit, *, iostat=stat) dummy, col_val if (stat /= 0) exit current_size = current_size + 1 if (.not. allocated(second_col)) then ! 第一次分配数组 allocate(second_col(current_size)) else ! 扩展数组,用move_alloc高效转移数据 call move_alloc(second_col, second_col(current_size)) end if second_col(current_size) = col_val end do close(file_unit) ! 输出结果 print *, '动态提取的第二列数据:' do i = 1, current_size print *, second_col(i) end do end program dynamic_extract_col
关键细节说明
move_alloc是Fortran 2003及以上标准的命令,能高效地将原数组的内存转移到新的扩展数组,避免手动复制数据的开销- 不需要提前统计行数,程序会自动根据读取的行数扩展数组
内容的提问来源于stack exchange,提问作者Florian Hubart
相关产品推荐
相关产品推荐

