如何在Fortran90中用数字,单词和空白遍历字符串? [英] How to iterate over character strings with numbers, words and blancks in 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屋!