如何在Fortran90中用数字,单词和空白遍历字符串? [英] How to iterate over character strings with numbers, words and blancks in Fortran90?

查看:91
本文介绍了如何在Fortran90中用数字,单词和空白遍历字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文件说明:STL文件包含

Description of the file: The STL file consists of

solid <solid_name>
   facet normal n1 n2 n3 (the triangles normal vector)
      outerloop         (one of the markers I want to read)
      v1          x1 y1 z1
      v2          x2 y2 z2       (three vertex of the triangle/facet)    
      v3          x3 y3 z3
      endloop
   end facet
endsolid

想法是读取每一行中的信息.首先,我正在尝试!阅读第一行:固体

The idea is to read the information in each line. First, I'm trying !to read the first line:solid

program Leitura
        !use, intrinsic :: trim
        implicit none
        integer ilo, ierror, ihi, ios, iunit, num_text, len_blanck, 
        len_word,        
        len_text, i
        character(len=80) :: filename
        character(len=:), dimension(:), allocatable :: text, lenc
        character(len=:), dimension(:), allocatable :: word
        character(len=:), dimension(:), allocatable :: blanck
        len_blanck=1
        len_word=11
        len_text=256
        allocate(character(len=len_blanck) :: blanck(1))
        allocate(character(len=len_word) :: word(1))
        allocate(character(len=len_text) :: text(1))
        allocate(character(len=len_text) :: lenc(1))
        blanck= " "
        ierror = 0
        iunit=10
        filename="Esfera.stl"

        !Opening the STL file
        open(unit=iunit, file=filename, status='old', access='stream',    form='unformatted')


        !  If NUM_TEXT is zero, then initialize TEXT.
        !
        if ( num_text <= 0 ) then
            num_text = 0
            text = blanck
        end if
        !
        !  If TEXT is blank, try to read a new line from the file.
        if ( ios /= 0 ) then
            ierror = 1
            word = blanck
            text = blanck
            return
        end if

        num_text = num_text + 1
        !Reading the first line of information- should be solid name, aka,             !       !the name of the solid
        read ( iunit, '(a)', iostat = ios ) text
        do i=1,len(text)
            if ( text(i)==blanck ) then
                word = blanck
                return
            end if
        end do

       !
       !  Extract the next word from TEXT into WORD and return.
       !
        lenc = len_trim ( text )
       !
       !  Find ILO, the index of the first nonblank in TEXT.
       !
       ilo = 1

       do while ( text(ilo:ilo) == blanck )
           ilo = ilo + 1
       end do
      !
      !  Find IHI, the index of the last consecutive nonblank after the one
              ! at ILO.
      !
      ihi = ilo

      do while ( ihi+1 <= lenc )
          if ( text(ihi+1:ihi+1) == blanck ) then
              exit
          end if
          ihi = ihi + 1
      end do
    !
    !  Set WORD.
    !
      word = text(ilo:ihi)
    !
    !  Slide TEXT to the left.
    !
      if ( ihi+1 <= lenc ) then
          text = text(ihi+1:)
      else
          text = ' '
      end if

      return
end program Leitura

推荐答案

我没有时间写一个完整的答案,但是以下内容片段应该使您开始使用有效的代码.

I don't have the time to write a complete answer but the following fragments should get you started towards a working code.

首先,我认为您试图通过错误的方向前进读取时解析STL文件.STL文件格式相当在实际操作中,一个示例与以下示例之间的差异很小下一个.它不像某些具有上千种不同类型的文件格式线和一点线索下一步会发生什么.我们先假设输入文件的结构合理.我们将从代码开始几乎没有任何错误处理,因为:

First off, I think you're going in the wrong direction by trying to parse the STL file as you read it. The STL file format is fairly clean with little, in practice, variation between one example and the next. It's not like some file formats with a thousand different types of line and little clue what's coming next. We'll start by assuming that the input file is well structured. And we'll start with a code that has almost no error processing at all because:

  • 几乎不需要;
  • 包括它可以掩盖此答案的重要部分进入许多ifs和其他情况;和
  • 除非您打算编写代码来修复损坏的STL文件,唯一需要进行的错误处理是报告无法读取文件中显示为可靠.

当然,我们将从一些数据结构开始,特别是一种用于实体,一种用于小面.喜欢这个:

We will start, of course, with some data structures, specifically one for the solid and one for the facets. Like this:

  TYPE facet
     REAL, DIMENSION(3) :: normal
     REAL, DIMENSION(3,3) :: vertices
  END TYPE facet

  TYPE solid
     CHARACTER(len=64) :: label
     TYPE(facet), DIMENSION(:), ALLOCATABLE :: facets
  END TYPE solid

  TYPE(solid) :: model

我将包装代码以将文件读取到函数中,然后像使用它一样使用这个:

I'll wrap the code to read the file into a function, and use it like this:

  model = read_solid('filename.stl')

现在,对它的实质是函数定义

Now, to the meat of it, the function definition

FUNCTION read_solid(fn) RESULT(mdl)
  ! Read solid from file fn
  CHARACTER(*), INTENT(in) :: fn
  TYPE(solid) :: mdl
  ! Local variables
  INTEGER :: nu
  INTEGER :: ix, jx, num_facets
  CHARACTER(len=132) :: line
  CHARACTER(len=8) :: word1, word2
  ! Executables
  num_facets = 0
  OPEN(newunit=nu, file=fn, status='old')

读取文件,计算构面数,为其分配空间,然后快退

Read the file, count the number of facets, allocate space for them, then rewind

ios = 0
! Now find out how many facets there are in the file
DO WHILE (ios==0)
   READ(nu,'(a132)',iostat=ios) line
   ! Count the facets in the file
   line = ADJUSTL(line)
   IF (line(1:5)=='facet') num_facets = num_facets+1
END DO

ALLOCATE(mdl%facets(num_facets))
REWIND(nu)

从头开始再次读取文件,通过此步骤即可获得可靠的结果:

Read the file again from the beginning, get the solid on this pass:

ios = 0
! Ignore any leading blank lines
sol: DO WHILE (ios==0)
   READ(nu,'(a132)',iostat=ios) line
   ! If the line is empty, get the next one
   IF (LEN_TRIM(line)==0) CYCLE sol

使用 adjustl

   line = ADJUSTL(line)
   IF (line(1:5)=='solid') THEN
      ! We've already read the line from the file, now use an
   internal read
      READ(line,*) word1, mdl%label
      EXIT sol
      ELSE ! The line didn't start with 'solid'
         ! Do something
   END IF
END DO sol

变量 word1 word2 用于捕获"字符串,而我们不是真正感兴趣的是,它们的内容被忽略了.下一个块读取刻面.

The variables word1 and word2 are used to 'catch' strings we're not really interested in, their contents are ignored. The next block reads the facets.

fct: DO ix = 1, num_facets
   DO WHILE (ios==0)
      READ(nu,'(a132)',iostat=ios) line
      IF (LEN_TRIM(line)==0) CYCLE fct ! ignore any blank lines
      line = ADJUSTL(line)
      IF (line(1:5)=='facet') THEN
         READ(line,*) word1, word2, mdl%facets(ix)%normal
         READ(nu,*) aline ! this should be 'outer loop' and we ignore it
         DO jx = 1, 3
            READ(nu,*) word1, mdl%facets(ix)%vertices(jx,:)
         END DO
      ELSE ! The line didn't start with 'facet'
         ! Do something
      END IF
   END DO
END DO fct

CLOSE(nu)

! If anything has gone wrong reading the file, return an empty solid.
IF (ios/=0) DEALLOCATE(mdl%facets)

END FUNCTION read_solid

我的方法与OP的主要区别在于,我依靠 list-directed 输入来照顾在行中查找字段以及正确读取字符串,实数等内容的情况.如果STL文件是干净的,这是一种明智的方法,如果您使用的是肮脏的STL文件,请从源头修复它们.

The main difference between my approach and OP's is that I rely on list-directed input to take care of finding fields in lines, and in reading strings, reals, etc, properly. If the STL file is clean this is a sensible approach, if you're working with dirty STL files, fix them at source.

最后,这实际上并没有回答OP有关如何逐个字符读取字符串并对其进行解释的问题.它也不能解决发布的OP代码中出现的任何错误.

And, finally, this doesn't actually answer OP's question(s) about how to read strings character-by-character and interpret them. Nor does it fix any of the errors manifest in the code OP posted.

这篇关于如何在Fortran90中用数字,单词和空白遍历字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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