【问题标题】:How to iterate over character strings with numbers, words and blancks in Fortran90?如何在Fortran90中迭代带有数字、单词和空格的字符串?
【发布时间】:2020-01-04 10:10:04
【问题描述】:

文件说明: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

【问题讨论】:

  • 我正在尝试在这里发布整个代码,但我遇到了麻烦...

标签: arrays string fortran character fortran90


【解决方案1】:

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

首先,我认为您尝试 在阅读时解析 STL 文件。 STL文件格式相当 干净,在实践中,一个例子和一个例子之间几乎没有变化 下一个。它不像某些具有一千种不同类型的文件格式 线和一点线索接下来会发生什么。我们首先假设 输入文件结构良好。我们将从代码开始 几乎没有错误处理,因为:

  • 几乎不需要;
  • 包括它会掩盖这个答案的重要部分 进入许多 if 和 else;和
  • 除非您打算编写代码来修复损坏的 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)

从头再读一遍文件,在这个pass上得到solid:

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

变量word1word2 用于“捕获”我们没有的字符串 真正感兴趣的,他们的内容都被忽略了。下一个块读取构面。

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 文件,请从源头修复它们。

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

【讨论】:

  • 非常非常感谢,马克!这帮助很大。
  • 嘿,马克!你好吗?我已经设法修复了我的程序,现在我能够正确读取任何 STL 文件。但是,现在我无法将我作为字符读取的数据转换为实数。假设文件的第一个 facet 是:solid model facet normal 0.0 0.0 -1.0 outer loop vertex 20.0 0.0 0.0 vertex 0.0 -20.0 0.0 vertex 0.0 0.0 0.0 endloop endfacet 如何将信息作为字符读取并将它们转换为实数?
  • 但是上面的代码将实数读入实变量!如果您遵循我的代码,我不明白您如何将数字读取为字符串。
  • 我知道,现在运行良好。非常感谢您的帮助!
猜你喜欢
  • 2010-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
相关资源
最近更新 更多