gpt4 book ai didi

arrays - Fortran 用户定义运算符中未分配的假定形状数组的问题

转载 作者:行者123 更新时间:2023-12-01 12:05:53 25 4
gpt4 key购买 nike

我正在尝试实现一个 python 类型的 in 运算符来检查一维数组是否包含某个元素。原则上我可以使用它,但是我无法涵盖我想要使用的两种类型的数组,即固定大小的数组和可分配的数组。下面我有一段代码几乎可以满足我的要求:

MODULE operator_in
IMPLICIT NONE

INTERFACE OPERATOR(.IN.)
MODULE PROCEDURE in_integer_list
! MODULE PROCEDURE in_integer_list_alloc
END INTERFACE OPERATOR(.IN.)

CONTAINS
FUNCTION in_integer_list(key, list) RESULT(res)
IMPLICIT NONE
INTEGER, INTENT(IN) :: key
INTEGER, INTENT(IN) :: list(:)
LOGICAL :: res

INTEGER :: ii

res = .FALSE.
DO ii = 1,SIZE(list)
IF (key == list(ii)) THEN
res = .TRUE.
RETURN
END IF
END DO
END FUNCTION in_integer_list

FUNCTION in_integer_list_alloc(key, list) RESULT(res)
IMPLICIT NONE
INTEGER, INTENT(IN) :: key
INTEGER, ALLOCATABLE, INTENT(IN) :: list(:)
LOGICAL :: res

IF (ALLOCATED(list)) THEN
res = in_integer_list(key, list)
ELSE
res = .FALSE.
END IF
END FUNCTION in_integer_list_alloc

END MODULE operator_in


PROGRAM test

USE operator_in

INTEGER :: list1(5) = (/1, 4, 6, 3, 8/)
INTEGER, ALLOCATABLE :: list2(:), list3(:)
INTEGER :: ii


ALLOCATE(list2(7))
list2(:) = (/8,7,6,5,4,2,1/)

DO ii = 1,5
IF (ii .IN. list1) THEN
WRITE (*,'(I3,A,5I3)') ii, ' is in ', list1
END IF
IF (ii .IN. list2) THEN
WRITE (*,'(I0.3,A,7I3)') ii, ' is in ', list2
END IF
! IF (ii .IN. list3) THEN
! WRITE (*,'(I3,A,7I3)') ii, ' is in ', list3
! END IF
END DO

END PROGRAM test

按原样,代码产生以下输出:

  1 is in   1  4  6  3  8
1 is in 8 7 6 5 4 2 1
2 is in 8 7 6 5 4 2 1
3 is in 1 4 6 3 8
4 is in 1 4 6 3 8
4 is in 8 7 6 5 4 2 1
5 is in 8 7 6 5 4 2 1

但是,如果我取消对最后三行的注释,

     IF (ii .IN. list3) THEN
WRITE (*,'(I0.3,A,7I3)') ii, ' is in ', list3
END IF

代码因段错误而崩溃,因为 list3 未分配:

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0 0x10925ebe4
#1 0x10925e306
#2 0x7fff5e878b5c
#3 0x1092547da
#4 0x109254bc5
#5 0x109254cce
Segmentation fault: 11

我试图通过编写第二个函数 (in_integer_list_alloc) 来解决这个问题,该函数允许分配数组,但在我的界面中声明了这两个函数:

  INTERFACE OPERATOR(.IN.)
MODULE PROCEDURE in_integer_list
MODULE PROCEDURE in_integer_list_alloc
END INTERFACE OPERATOR(.IN.)

给我一​​个歧义错误:

   FUNCTION in_integer_list(key, list) RESULT(res)
1
user-defined_operator.f90:27:2:

FUNCTION in_integer_list_alloc(key, list) RESULT(res)
2
Error: Ambiguous interfaces in operator interface 'in' for 'in_integer_list' at (1) and 'in_integer_list_alloc' at (2)

如果我注释掉界面中的第一个过程:

  INTERFACE OPERATOR(.IN.)
! MODULE PROCEDURE in_integer_list
MODULE PROCEDURE in_integer_list_alloc
END INTERFACE OPERATOR(.IN.)

我当然遇到固定大小数组 list1 的问题:

      IF (ii .IN. list1) THEN
1
Error: Operands of user operator 'in' at (1) are INTEGER(4)/INTEGER(4)

那么:有没有一种巧妙的方法来实现我想要的,或者至少在代码因未分配传递的数组而崩溃时获得正确的错误消息?

最佳答案

理想情况下,重新设计您的代码,这样就无需处理未分配的数组。如果您想表示一个空列表,请使用分配的零大小数组。

(未分配的对象在概念上更适合“没有列表”,而不是“列表为空”。从概念上讲,您不应该查询不存在的东西。)

如果必须,您可以按照以下行编写一个单参数适配器函数:

FUNCTION foo(arg)
INTEGER, INTENT(IN), OPTIONAL:: arg(:)
INTEGER, ALLOCATABLE :: foo(:)
IF (PRESENT(arg)) THEN
foo = arg
ELSE
foo = [INTEGER ::]
END IF
END FUNCTION foo

然后可以使用适配器:

 IF (item .in. foo(list)) THEN
...

适配器函数的适当命名留给读者。

(适配器已使用虚拟参数 OPTIONAL 编写,以适应实际参数不存在、实际参数未分配和实际参数分离。这是 Fortran 2008 功能。)

关于arrays - Fortran 用户定义运算符中未分配的假定形状数组的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57008359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com