读取文本文件,其中列具有特定格式

时间:2019-06-04 19:06:57

标签: fortran gfortran fortran90 fortran77 fortran95

我正在使用Fortran,我需要读取一个包含3列的文件。问题是第三列是整数的组合,例如120120101,我需要将每个单个值分隔在不同的列中。

通常,我手动删除前两列,因此文件看起来像:

Info
0120012545
1254875541
0122110000
2254879933

要读取此文件(其中每个值都在不同的列中),我可以使用以下Fortran子例程:

subroutine readF(imp, m, n)
  implicit none
  integer :: n,m,i,imp(n,m)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(*(i1))') imp(i,1:m)
    end do
  close(unit=100)
end subroutine readF

我想知道是否可以读取具有以下内容的文件:

IDs Idx Info
ID001 1 125478521111
ID002 1 525478214147
ID003 2 985550004599
ID004 2 000478520002

,结果如下:

ID001 1 1 2 5 4 7 8 5 2 1 1 1 1
ID002 1 5 2 5 4 7 8 2 1 4 1 4 7
ID003 2 9 8 5 5 5 0 0 0 4 5 9 9
ID004 2 0 0 0 4 7 8 5 2 0 0 0 2

第3列中的值在m列中分散。

第一行是标题,但我不需要它,因此我从第二行开始阅读。

我尝试使用下面的子例程编写程序,但没有用:

subroutine readF(imp, ind, m, n)
  implicit none
  integer :: n,m,i,imp(n,m),ind(n),chip(n)
  open(unit=100, file='file.txt', status='old', action='read')
  do i=2,n
    read(100,'(i8,i1,*(i1))') ind(i),chip(i),imp(i,1:m)
  end do
  close(unit=100)
end subroutine readF

有人知道我可以在不手动删除前两列的情况下读取该文件吗?

谢谢。

1 个答案:

答案 0 :(得分:1)

我将猜测每个变量的含义,并尝试解释一些明显的错误。

我相信您的do i=2,n是一个错误,因为我已经看到一些学生犯了这个错误。从2开始i并不意味着您正在从第二行开始读,而仅仅是i的值。然后,假设您有n条数据线,您将错过最后一条数据线,因为您正在读取n-1条线。您想要的是循环之前的空白读取语句。这跳过标题行。那你要我从1转到n。

根据read语句中变量的顺序,我假设ind是ID号,chip是IDx数,imp的Info数均为1的整数最多m个。

您的i8将获取信息的前8列,并尝试将它们解释为整数。好吧,ID001 1 1是第一条数据线的前8列,它不是整数。您需要跳过“ ID”,并将“ 001”读入ind。然后跳过1个字符,将1个整数读入芯片,然后再跳过1个字符,然后一次读取1个整数,读入Info。 x格式说明符跳过1个字符。

对于每个要单独放入imp的整数,您需要一个从1到m的隐式do循环。我在那里用了j。如果您不知道隐式的do循环,请用google搜索。在Fortran中这是非常标准的。

此代码段将执行以下操作:

open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,'(2x,i3,1x,i1,1x,*(i1))') ind(i),chip(i),(imp(i,j),j=1,m)
end do
close(unit=100)

用于回答评论的其他答案。我看你会有两个选择。首先,进行行解析。我不会选择这个。

第二个选项是使用未格式化的输入来读取行。未格式化的输入使用空格分隔输入项。我将使第三个项目的字符变量足够长以容纳m的长度。可以使用Fortran的read语句读取此字符变量。这称为从内部记录中读取。您将像以前一样读取每个整数。看起来像这样:

character(len=m) :: Info
character(len=:),allocatable :: Dumb
open(unit=100, file='file.txt', status='old', action='read')
read(100,*)  ! This skips the header line.
do i=1,n     ! Read in n data lines.
  read(100,*) Dumb, chip(i), Info
  read(Info,'(*(i1))') (imp(i,j),j=1,m)
end do
close(unit=100)

do循环中的第一个read语句正在从文件读取。不管其长度如何,它都会将整个第一列粘贴到Dumb中,将第二列粘贴到chip(i)中,并将整个第三列粘贴到一个名为Info的字符串中。

第二条读取语句正在从“内部记录”信息中读取。您可以在字符串上使用read语句。在这里,我使用格式说明符和隐式的do循环来一次提取1个整数。