gfortran无法编译实数变量

4

我已经用Fortran90编写了一个简单的程序来计算三角形的面积。用户输入三角形的三条边,然后程序输出面积。非常简单。

MODULE Triangle_Operations
    IMPLICIT NONE
CONTAINS
    FUNCTION Area(x,y,z)
        REAL :: Area  ! function type
        REAL, INTENT( IN ) :: x, y, z
        REAL :: theta, height
        theta = ACOS((x**2+y**2-z**2)/(2.0*x*y))
        height = x*SIN(theta); Area = 0.5*y*height
    END FUNCTION Area
END MODULE Triangle_Operations

PROGRAM Triangle
    USE Triangle_Operations
    IMPLICIT NONE
    REAL :: a, b, c, Area
    PRINT *, 'Welcome, please enter the &
              &lengths of the 3 sides.'
    READ *, a, b, c
    PRINT *, 'Triangle''s area: ', Area(a,b,c)
END PROGRAM Triangle

当我使用gfortran编译triangle1.f90时,会收到以下错误信息:

triangle1.f90:16.25:

    REAL :: a, b, c, Area
                         1
triangle1.f90:14.8:

    USE Triangle_Operations
        2
Error: Symbol 'area' at (1) conflicts with symbol from module 'triangle_operations', use-associated at (2)
triangle1.f90:19.13:

    READ *, a, b, c
             1
Error: Symbol 'a' at (1) has no IMPLICIT type
triangle1.f90:19.16:

    READ *, a, b, c
                1
Error: Symbol 'b' at (1) has no IMPLICIT type
triangle1.f90:19.19:

    READ *, a, b, c
                   1
Error: Symbol 'c' at (1) has no IMPLICIT type

为什么变量a,b,c会出现错误?我已经明确将它们定义为实数。


对我来说,它编译(和运行)得很好。当我第一次这样做时,我将文件命名为“t.f”,结果出现了与你类似的错误。当我将其重命名为“t.f90”时,就可以成功编译了。 - wallyk
@wallyk 这很奇怪。我有一个名为 triangle1.f90 的文件。也许我需要更改扩展名,或者使用特定的编译器?我还不知道... - ShanZhengYang
5
我认为你的编译器因为"Area"的多次声明而产生了一系列错误(第一个错误)。在主程序中不需要将其声明为REAL,因为它已经在模块中声明过了。删除这个声明可以解决所有问题。 - RussF
1个回答

1
问题在于你在主程序和导入的模块中都定义了Area,名称冲突。你可能认为需要在主程序中定义Area,这是早期(更暗淡的)时期在没有显式接口的情况下调用函数的遗留物。在现代Fortran中,模块会自动提供接口,语句use Triangle_operations就足够了。
要解决问题,请从主程序中删除对Area的声明,例如:
REAL :: a, b, c, Area

转换为

REAL :: a, b, c

你的编译输出中后续的错误都是由于关于Area的第一个错误引起的。整行都被作废了,所以abc的类型声明没有被处理,这导致编译器在下次遇到它们时抱怨缺少类型。如果按照上面建议的修复方法进行修复,这些错误将会消失。
如果你的意图是在主程序中有一个名为Area的变量来存储模块函数调用的结果,你可以重命名模块符号,例如。
use triangle_operations, triangleArea => Area

然后执行这个操作:
real a, b, c, Area
Area = triangleArea(a,b,c)

在你的主程序中。

(只是一个个人问题)我猜在许多现代语言中,通常认为只导入当前范围中要使用的特定变量或对象是一种良好的实践,而不是隐式地导入模块中的所有内容。因此,我总是遵循在Fortran中将“only”与“use”一起使用的规则。您对这种做法有什么看法...?我认为这也可能对OP看到“Area”的冗余性有所帮助。 - roygvib
@roygvib 就像其他编程语言一样,有时您会导入所有内容,有时则会使用 only。 当您使用 only 时,每当您添加或重命名某些内容时,都必须采用它,但它有助于跟踪这些内容。 如果你将某些东西导入到小的子程序中,我不会担心,但有时它很方便。 对此没有严格的规定。 - Vladimir F Героям слава
@VladimirF 是的,当然没有严格的规则,这也是一种风格问题。实际上,在许多大型程序中都使用了两种策略(即仅附加仅列表或从不附加它)。对于短程序来说,导入所有内容也非常方便。另一方面,随着程序变得越来越大,将所有内容隐式导入当前范围会使跟踪变量变得困难。我希望未来的Fortran版本会有类似于“use,explicit :: mymod”的东西,并允许像其他语言一样调用“call mymod%myfunc()” :) - roygvib
由于这与楼主的问题无关,我稍后会删除我的评论。 - roygvib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接