在Fortran中读取整数列表文件 [英] Reading a file of lists of integers in Fortran

查看:273
本文介绍了在Fortran中读取整数列表文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Fortran程序读取数据文件,其中每一行都是一个整数列表。

I would like to read a data file with a Fortran program, where each line is a list of integers.

每行都有可变数量的整数,分开

Each line has a variable number of integers, separated by a given character (space, comma...).

示例输入:

1,7,3,2
2,8
12,44,13,11

我有一个解决方案,可以拆分行,但是我发现这很麻烦:

I have a solution to split lines, which I find rather convoluted:

module split
    implicit none
contains
    function string_to_integers(str, sep) result(a)
        integer, allocatable :: a(:)
        integer :: i, j, k, n, m, p, r
        character(*) :: str
        character :: sep, c
        character(:), allocatable :: tmp

        !First pass: find number of items (m), and maximum length of an item (r)
        n = len_trim(str)
        m = 1
        j = 0
        r = 0
        do i = 1, n
            if(str(i:i) == sep) then
                m = m + 1
                r = max(r, j)
                j = 0
            else
                j = j + 1
            end if
        end do
        r = max(r, j)

        allocate(a(m))
        allocate(character(r) :: tmp)

        !Second pass: copy each item into temporary string (tmp),
        !read an integer from tmp, and write this integer in the output array (a)
        tmp(1:r) = " "
        j = 0
        k = 0
        do i = 1, n
            c = str(i:i)
            if(c == sep) then
                k = k + 1
                read(tmp, *) p
                a(k) = p
                tmp(1:r) = " "
                j = 0
            else
                j = j + 1
                tmp(j:j) = c
            end if
        end do
        k = k + 1
        read(tmp, *) p
        a(k) = p
        deallocate(tmp)
    end function
end module

我的问题


  • 在Fortran中是否有一种更简单的方法?我的意思是,在不知道要读取的值数量的情况下,读取值列表。上面的代码看起来很尴尬,在Fortran中文件I / O看起来并不容易。

  • Is there a simpler way to do this in Fortran? I mean, reading a list of values where the number of values to read is unknown. The above code looks awkward, and file I/O does not look easy in Fortran.

此外,主程序还必须读取长度未知且无界的行。如果我假设它们的长度相同(参见下文),我就能读取它们,但是我不知道如何读取无界线。我想它需要Fortran 2003的流功能,但我不知道该怎么写。

Also, the main program has to read lines with unknown and unbounded length. I am able to read lines if I assume they are all the same length (see below), but I don't know how to read unbounded lines. I suppose it would need the stream features of Fortran 2003, but I don't know how to write this.

这是当前程序:

program read_data
    use split
    implicit none
    integer :: q
    integer, allocatable :: a(:)
    character(80) :: line
    open(unit=10, file="input.txt", action="read", status="old", form="formatted")
    do
        read(10, "(A80)", iostat=q) line
        if(q /= 0) exit
        if(line(1:1) /= "#") then
            a = string_to_integers(line, ",")
            print *, ubound(a), a
        end if
    end do
    close(10)
end program

A评论关于这个问题的问题:通常我会在Python中执行此操作,例如,转换一行就像 a = [line.split(,)]中x的int(x)一样简单,读取文件同样几乎是一件微不足道的任务。我将使用Fortran DLL进行真实的计算。但是,我想提高我在文件I / O方面的Fortran技能。

A comment about the question: usually I would do this in Python, for example converting a line would be as simple as a = [int(x) for x in line.split(",")], and reading a file is likewise almost a trivial task. And I would do the "real" computing stuff with a Fortran DLL. However, I'd like to improve my Fortran skills on file I/O.

推荐答案

我不认为这是最短的时间,但是比您的短得多。一旦拥有它,就可以重用它。我并不完全同意这些说法,Fotran在字符串处理方面有多不好,我在Fortran中很好地进行了令牌化,递归下降解析和类似工作,尽管在其他一些语言中,拥有更丰富的库更容易。有时,您也可以使用用Fortran用其他语言编写的库(尤其是C和C ++)。

I don't claim it is the shortest possible, but it is much shorter than yours. And once you have it, you can reuse it. I don't completely agree with these claims how Fotran is bad at string processing, I do tokenization, recursive descent parsing and similar stuff just fine in Fortran, although it is easier in some other languages with richer libraries. Sometimes you can use the libraries written in other languages (especially C and C++) in Fortran too.

如果您始终使用逗号,则可以删除逗号替换,因此

If you always use the comma you can remove the replacing by comma and thus shorten it even more.

function string_to_integers(str, sep) result(a)
    integer, allocatable :: a(:)
    character(*) :: str
    character :: sep
    integer :: i, n_sep

    n_sep = 0
    do i = 1, len(str)
      if (str(i:i)==sep) then
        n_sep = n_sep + 1
        str(i:i) = ','
       end if
    end do
    allocate(a(n_sep+1))
    read(str,*) a
end function

缩短的可能:使用等价性<< c $ c> str 作为字符数组查看/ code>或转移,并在 allocate count() code>来获得 a 的大小。

Potential for shortening: view the str as a character array using equivalence or transfer and use count() inside of allocate to get the size of a.

这篇关于在Fortran中读取整数列表文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆