如何从ASCII STL文件中读取字符数组的数据,并将其转换为实数?

问题描述 投票:1回答:1

我正在编写一个Fortran程序,从ASCII STL文件中读取信息,并将其写入另一个文件。

该文件的结构如下。

solid model
    facet normal n1 n2 n3
        outer loop
            vertex v1x v1y v1z
            vertex v2x v2y v2z
            vertex v3x v3y v3z
        endloop
    endfacet
    facet normal n1' n2' n3'
        outer loop
            vertex v1x' v1y' v1z'
            vertex v2x' v2y' v2z'
            vertex v3x' v3y' v3z'
        endloop
    endfacet
    .
    .repeats 
    .
    endsolid

换句话说,文件由未知数量的三角面组成 每一个三角面都包含了上图所示的信息。

我使用字符可分配的字符数组来绕过必须指定输入文件的格式,因为它是变化的,我无法控制它。

这是必要的,因为我无法预先知道每个被读取的文件的精确格式,因为它们并不总是相同的。

另外,在这种文件格式下,我也没办法提前知道每个文件包含的面数。

到目前为止,我用来读取文件的策略是将一个字符数组声明为

   character(len=:), dimension(:), allocatable :: line

并分配和重新分配每行所需的可用位置数,因为它们各不相同。

如果我的理解正确的话,我的问题是,我无法在不指定每个位置长度的情况下分配数组 "行 "的位置。但事实上,我并不知道我需要提前分配每个位置的长度。例如,在这个文件中,我有这个面。

facet normal 0.000000e+00 -1.000000e+00 0.000000e+00
   outer loop
      vertex 0.000000e+00 0.000000e+00 0.000000e+00
      vertex 1.500000e+02 0.000000e+00 0.000000e+00
      vertex 0.000000e+00 0.000000e+00 5.000000e+01
   endloop
endfacet

而在另一个文件中,我有(注意,在这个文件中,"外循环 "是写在下一行,只从 "facet normal "之后的1个空格开始;在第一个文件中,有3个空格)。

facet normal -0.962637 0.19148 0.19148
 outer loop
  vertex 1.96194 0 1.30866
  vertex 2.03806 0.191342 1.5
  vertex 1.9971 0.191342 1.29409
 endloop
endfacet

*) 我怎么能用字符数组读取任何文件格式?这有可能吗?

2) 例如,如果我尝试

  allocate(character(len=*) :: line(5))

我得到了这个错误。

 allocate(character(len=*) :: line(5))

 internal compiler error: in gfc_trans_allocate, at fortran/trans-stmt.c:5697

 1face.f90:27:0: internal compiler error: Abort trap: 6
 gfortran: internal compiler error: Abort trap: 6 (program f951)
 Please submit a full bug report,
 with preprocessed source if appropriate.
 See <http://gcc.gnu.org/bugs.html> for instructions.

3) 如果我尝试

 allocate(character(len=:) :: line(5))

我得到

 allocate(character(len=:) :: line(5))
         1
 Error: Type-spec at (1) cannot contain a deferred type parameter 

4)我试过使用真实的格式来读取,但没有用,如果我试着使用一个真实的可分配变量,并将其分配给

 real, dimension(:), allocatable :: line
 allocate(line(5))

我的编译器并没有抱怨,但这个变量从文件中读取了垃圾。在上面同样的例子中,我得到

4.15787011E+21   1.24145785E+28   2.73757760E+20   4.00465633E-11   4.00463551E-11

5)最后,我试着把信息读成一个字符数组,如

read(unit=iunit, iostat=ios) line

读取数据后,我需要对数据进行计算,所以我想我可以把它转换成真正的一维数组,对吗?所以我想我可以把它转换为一个真正的一维数组,对吗?

我试过使用可分配字符数组来读取行数。

read(iunit, iostat=ios) line

并将其内容写入一个可分配的实数组(3维real_line)中,使用

write(line,*) real_line

但我得到

Fortran runtime error: End of record

有鉴于此,谁能帮帮我?我应该怎么做呢?我应该

  • 坚持读取字符并尝试用其他方式将数据转换为实数?

  • 试试别的方法?

arrays stl fortran character ascii
1个回答
0
投票

很久以前,我会使用

implicit none
integer ii
character*255 line
read(10,*) line
do ii =1,255
  if (line(ii:ii) .ne. " " ) then
   istart = ii
 endif

以此类推,将字符字符串的部分转换为适当的类型.iarray = int(char(istart:istop))例如

这不是一个正式的代码块。它的目的是为了传达逻辑。用户需要定义读取语句中使用的单位10,并为解析器声明其他变量。

这是一个字符解析器,当你可以检查数组中的每一个字符,并将其转换为实数或整数或任何东西。在任何文件上应该都能正常工作。

现在可能有更快捷的方法,但我的方法应该可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.