2014-12-05 240 views
1

我想要一个将数字 字符串的内容转换为数值类型(int,real,double precision,real(real128))的子例程。Fortran将字符串转换为数字

但是,当尝试使用Class(*)时出现错误。错误 如下所示:

gfortran -o build/lib/larsa.o -c -ffree-form -g -J./build/lib lib/larsa.f 
lib/larsa.f:1933.35: 

Read (s, frmt, iostat=ios) num 
           1 
Error: Data transfer element at (1) cannot be polymorphic unless 
it is processed by a defined  input/output procedure 
lib/larsa.f:1935.32: 

Read (s, *, iostat=ios) num 
          1 
Error: Data transfer element at (1) cannot be polymorphic unless 
it is processed by a defined input/output procedure 

这是我写的子程序。

Subroutine converts_str_to_num & 
    (       & 
    s, num,      & 
    fmt, wrn     & 
) 

Character (len=*), Intent (in) :: s 
Character (len=*), Intent (in), Optional :: fmt 

Class (*) :: num 
Character (len=*), Intent (inout), Optional :: wrn 

Integer :: ios 
Character (len=65) :: frmt 

!!$ Reads contents of s and puts value in i. 

If (Present (fmt)) Then 
    frmt = "(" // Trim (fmt) // ")" 
    Read (s, frmt, iostat=ios) num 
Else 
    Read (s, *, iostat=ios) num 
End If 

End Subroutine converts_str_to_num 
+1

你的问题是什么?错误消息非常明确:除非使用定义的I/O,否则不能在I/O列表中使用多态变量。你是在“这是什么意思?”之后? – francescalus 2014-12-05 21:38:31

+0

有没有解决方法,仍然有'类(*)'在那里? – Zeus 2014-12-05 21:39:50

+4

@ChristopherDimech是的,使用'select type'构造并为所有想要处理的类型写一个case。 – casey 2014-12-05 21:40:54

回答

4

要整理评论,我会提供一个答案。

错误消息很明显:除非列表由定义的输入/输出处理,否则输入/输出列表中不能有多态变量。这是Fortran 2008中的9.6.3.5。class(*) num是(无限制)多态。

现在,对于多态的派生类型,您可以定义这样一个定义的输入/输出过程,但这算作很多工作,并且gfortran当然不支持这个概念。此外,你不能为内在的类型做到这一点。这些因素意味着你必须处理输入列表中的非多态变量。

当然,可以使用泛型来避免多态性,但替代方案(因为它适用于所有多态)是使用select type构造。为简单起见,忽略表式和显式格式的情况:

select type (assoc => num) 
type is (int) 
    Read (s, *, iostat=ios) assoc 
type is (real) 
    ... 
type is (...) 
class default 
    error stop "Oh noes!" 
end select 

我在选择类型使用的关联名称来解决你的困惑的一个组成部分。如果你刚刚做了

select type(num) 
type is (int) 
    Read (s, *, iostat=ios) num 
end select 

认为,“现在使用num是好的:为什么呢?”那是因为num里面的结构和num不一样。至关重要的是,它不是多态,而是与type is匹配的确切类型。