如何在Fortran90中迭代带有数字,单词和布兰克的字符串?



文件描述: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

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

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

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

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

最新更新