You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:25:19