当输入文件中缺少其中一个变量时,从文件中读取已知数量的变量

时间:2012-04-10 19:43:13

标签: file-io fortran text-files

我已经检查了类似的帖子。 M. S. B.在Reading data file in Fortran with known number of lines but unknown number of entries in each line

给出了解决方案

所以,我遇到的问题是从文本文件中我试图读取输入。在一行中应该有3个变量。但有时输入文件可能有2个变量。在那种情况下,我需要将最后一个变量设为零。我尝试在IOSTAT中使用READ语句,但如果只有两个值则转到下一行并读取下一个可用值。当没有第三个值时,我需要在读取2个值后停在第1行。

我发现有一种方法可以做一个评论/除了我想要阅读的类型(在这种情况下我正在阅读浮点数而评论是一个字符),这使得IOSTAT> 0并且我可以使用作为支票。但如果在某些情况下我可能没有那个评论。我想确保它比它更有效。

部分代码

    read(15,*) x
    read(15,*,IOSTAT=ioerr) y,z,w
    if (ioerr.gt.0) then
        write(*,*)'No value was found'
        w=0.0;
        goto 409
        elseif (ioerr.eq.0) then
        write(*,*)'Value found', w
        endif
  409   read(15,*) a,b
        read(15,*) c,d

INPUT FILE的格式为

    -1.000  abcd                                                                        
    12.460  28.000  8.00 efg                                                                            
    5.000   5.000   hijk                                                                            
    20.000  21.000  lmno                                                                            

即使没有“8.00 efg”

,我也需要让它工作

对于这种情况

    -1.000  abcd                                                                        
     12.460 28.000                                                                              
     5.000  5.000   hijk                                                                            
     20.000 21.000  lmno

我无法使用MSB建议的字符串方法。还有其他方法吗?

5 个答案:

答案 0 :(得分:0)

我似乎记得在过去尝试做类似的事情。如果您知道文件行的大小不会超过某个数字,您可能会尝试以下内容:

...
character*(128) A  

read(15,'(A128)') A  !This now holds 1 line of text, padded on the right with spaces
read(A,*,IOSTAT=ioerror) x,y,z
if(IOSTAT.gt.0)then
   !handle error here
endif

我不完全确定这个解决方案从一个编译器到另一个编译器的可移植性如何,我现在没有时间在f77标准中阅读它...

答案 1 :(得分:0)

我有一个例程来计算一行的实数。我认为你可以很容易地适应你的目的。

subroutine line_num_columns(iu,N,count)
    implicit none

    integer(4),intent(in)::iu,N

    character(len=N)::line
    real(8),allocatable::r(:)
    integer(4)::r_size,count,i,j

    count=0 !Set to zero in case of premature return

    r_size=N/5 !Initially try out this max number of reals
    allocate(r(r_size))

    read(iu,'(a)') line

50  continue
    do i=1,r_size
        read(line,*,end=99) (r(j),j=1,i) !Try reading i reals
        count=i
        !write(*,*) count
    enddo
    r_size=r_size*2 !Need more reals
    deallocate(r)
    allocate(r(r_size))
    goto 50

    return

99  continue
    write(*,*) 'I conclude that there are ',count,' reals on the first line'


end subroutine line_num_columns

答案 2 :(得分:0)

如果Fortran 90解决方案没问题,您可以使用以下过程来解析具有多个实际值的行:

subroutine readnext_r1(string, pos, value)
  implicit none
  character(len=*), intent(in)    :: string
  integer,          intent(inout) :: pos
  real,             intent(out)   :: value

  integer                         :: i1, i2

  i2 = len_trim(string)

  ! initial values:
  if (pos > i2) then
     pos   = 0
     value = 0.0
     return
  end if

  ! skip blanks:
  i1 = pos
  do
     if (string(i1:i1) /= ' ') exit
     i1 = i1 + 1
  end do

  ! read real value and set pos:
  read(string(i1:i2), *) value
  pos = scan(string(i1:i2), ' ')
  if (pos == 0) then
     pos = i2 + 1
  else
     pos = pos + i1 - 1
  end if

end subroutine readnext_r1

子程序从字符串'pos'开始读取字符串'string'中的下一个实数,并返回'value'中的值。如果已达到字符串的结尾,则'pos'设置为零(并返回值0.0),否则'pos'将递增到读取的实数后面的字符位置。

因此,对于您的情况,您首先要将该行读取为字符串:

character(len=1024) :: line
...
read(15,'(A)') line
...

然后解析此字符串

real    :: y, z, w
integer :: pos
...
pos = 1
call readnext_r1(line, pos, y)
call readnext_r1(line, pos, z)
call readnext_r1(line, pos, w)
if (pos == 0) w = 0.0

其中最后的'if'甚至不是必需的(但这样它更透明imho)。

请注意,如果该行上的第三个条目不是实数,则此技术将失败。

答案 3 :(得分:0)

您可以使用奇妙命名的冒号编辑描述符。如果I / O列表中没有其他项目,则允许您跳过格式的其余部分:

Program test

  Implicit None

  Real :: a, b, c
  Character( Len = 10 ) :: comment


  Do

     c = 0.0
     comment = 'No comment'
     Read( *, '( 2( f7.3, 1x ), :, f7.3, a )' ) a, b, c, comment

     Write( *, * ) 'I read ', a, b, c, comment

  End Do

End Program test

例如,我得到了gfortran:

Wot now? gfortran -W -Wall -pedantic -std=f95 col.f90
Wot now? ./a.out
  12.460  28.000  8.00 efg
 I read    12.460000       28.000000       8.0000000     efg       
  12.460  28.000  
 I read    12.460000       28.000000      0.00000000E+00           
^C

这适用于gfortran,g95,NAG编译器,Intel编译器和Sun / Oracle编译器。但是,我应该说我并不完全相信我理解这一点 - 如果c或注释未被读取,它们是否保证分别为0和所有空格?不确定,需要问别处。

答案 4 :(得分:0)

我知道以下简单的解决方案:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-pane">
<div>
    <img class="circle" src="one.jpg"/>
    <img class="circle" src="two.jpg"/>
    <img class="circle" src="three.jpg"/>
</div>

<div>
    <img class="square" src="one.jpg"/>
    <img class="square" src="four.jpg"/>
    <img class="square" src="six.jpg"/>
</div>
</div>

但它包含“goto”运算符

相关问题