如何在 Fortran 90 中迭代包含数字、单词和空格的字符串?

2024-05-07

文件说明:STL文件由以下部分组成

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

这个想法是阅读每一行中的信息。首先,我正在尝试阅读第一行: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

我没有时间写完整的答案,但以下内容 片段应该可以帮助您开始编写工作代码。

首先,我认为你试图走向错误的方向 当您阅读 STL 文件时对其进行解析。 STL文件格式相当 实际上,一个示例与实际示例之间的差异很小 下一个。它不像某些具有上千种不同类型的文件格式 线路和几乎不知道接下来会发生什么。我们首先假设 输入文件结构良好。我们将从代码开始 几乎没有错误处理,因为:

  • 几乎不需要;
  • 包括它会掩盖这个答案的重要部分 陷入大量的“如果”和“其他”;和
  • 除非您打算编写代码来修复损坏的 STL 文件, 唯一需要的错误处理是报告读取失败 文件中的实体。

当然,我们将从一些数据结构开始, 具体来说,一种用于实体,另一种用于刻面。喜欢 这:

  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

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

  model = read_solid('filename.stl')

现在,重点是函数定义

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')

读取文件,计算面的数量,为它们分配空间,然后倒带

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)

从头开始再次读取文件,获得此通道的实体:

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 and word2用于“捕获”我们不捕获的字符串 真正感兴趣的,他们的内容被忽略。下一个块读取方面。

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的主要区别在于我依赖于列表导向输入以正确查找行中的字段以及读取字符串、实数等。如果 STL 文件是干净的,这是一个明智的方法,如果您使用的是脏 STL 文件,请从源头修复它们。

最后,这实际上并没有回答OP关于如何逐个字符读取字符串并解释它们的问题。它也没有修复发布的代码 OP 中明显的任何错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Fortran 90 中迭代包含数字、单词和空格的字符串? 的相关文章

随机推荐