Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 指向由映射定义的子数组的指针_Arrays_Pointers_Fortran - Fatal编程技术网

Arrays 指向由映射定义的子数组的指针

Arrays 指向由映射定义的子数组的指针,arrays,pointers,fortran,Arrays,Pointers,Fortran,我想定义一个指向子数组的指针。对于一个简单的范围,这可以通过pointer=>array(i:j)轻松实现,但对于k=[k1,k2,k3]这样的映射,我不知道如何实现这一点。如果我要定义另一个数组,我可以使用一个循环,比如array2=[(array1(k(j)),j=1,size(k,1))]。但不可能以类似的方式分配指针(pointer=>[(array1(k(j)),j=1,size(k,1))]),因为表达式的r.h.s.似乎定义了另一个变量,而该变量甚至没有target属性。对于简单的

我想定义一个指向子数组的指针。对于一个简单的范围,这可以通过
pointer=>array(i:j)
轻松实现,但对于
k=[k1,k2,k3]
这样的映射,我不知道如何实现这一点。如果我要定义另一个数组,我可以使用一个循环,比如
array2=[(array1(k(j)),j=1,size(k,1))]
。但不可能以类似的方式分配指针(
pointer=>[(array1(k(j)),j=1,size(k,1))]
),因为表达式的r.h.s.似乎定义了另一个变量,而该变量甚至没有target属性。对于简单的任务,一个技巧是首先指定一个指向总数组的指针,以使用读出上的映射。但就我而言,这似乎是不可能的

我将附上一些例子:第一个例子展示了我上面描述的内容。第二个是一个更复杂的例子,这个技巧不再有效了。此外,还需要一张二维地图

最简单的例子:

program test

integer, parameter :: n=10,n_k=3
real,target :: a(1:n)
real :: b(1:n_k)
integer :: k(1:n_k)
integer :: j
real,pointer :: p(:)

! fill array a and define map k:
a=[(real(j),j=1,n)]
k=[((j+1)*2,j=1,n_k)]

! can be used to print the arrays:
!write(*,*) a
!write(*,*) k
! can be used to write only the part of a defined by k:
!write(*,*) (a(k(j)),j=1,n_k)

! this an similar things didn't work:
!p(1:n_k) => [(a(k(j)),j=1,n_k)]

! works, but not generally:
p => a
write(*,*) (p(k(j)),j=1,n_k)

! works, only for arrays:
b=(/(a(k(j)),j=1,n_k)/)
write(*,*) b

end program
更复杂的(但也是一种最小的)例子,它显示了(希望)我真正的问题。为了便于理解,需要一些解释。有很多写入命令可以打印数组。我很欣赏这么多代码,但我真的不知道如何制作一个简短易懂的工作示例:

module mod1

type base
   real :: a
end type

type,extends(base) ::  type1
end type

type,extends(base) :: type2
   type(type1),allocatable :: b(:)
end type

type(type2),allocatable,target :: c(:)

contains

subroutine printer(z)
   class(*),pointer,dimension(:) :: z
   integer :: j,a_z,n_z
   character(len=40) :: f,ff='(F10.2,1x))',form_z

   ! define format for printing:
   a_z=lbound(z,1)
   n_z=ubound(z,1)
   write(f,'(I0)') (n_z-a_z+1)
   form_z="("//trim(adjustl(f))//ff

   ! writing:
   select type(z)
   class is (base)
      write(*,form_z) (z(j)%a,j=a_z,n_z)
   end select
end subroutine

end module

program test

use mod1

integer,parameter :: n_b=8,n_c=6,n_js=3,n_ls=2
integer :: js(1:n_js),ls(1:n_ls)
integer :: j,l
class(*),pointer :: p(:)
character(len=40) :: f,ff='(F10.2,1x))',form_c,form_b

! define format for printing:
write(f,'(I0)') n_b
form_b="("//trim(adjustl(f))//ff
write(f,'(I0)') n_c
form_c="("//trim(adjustl(f))//ff

! creating and filling the arrays:
allocate(c(n_c))
c%a=[(2d0*real(j),j=1,n_c)]
do j=1,n_c
   allocate(c(j)%b(n_b))
   c(j)%b%a=[(real(l)*1d1**(j-1),l=1,n_b)]
end do

! write arrays to compare later:
write(*,form_c) c%a
write(*,*)
write(*,form_b) (c(j)%b%a,j=1,n_c)
write(*,*)

! denfining two maps (size and entries will be input in the final program):
js=[1,4,6]
ls=[2,7]

! using the maps to print only the desired entries:
write(*,*) (c(js(j))%a,j=1,n_js)
write(*,*)
write(*,*) ((c(js(j))%b(ls(l))%a,j=1,n_js),l=1,n_ls)
write(*,*)

! !!! here I want to use the maps as well, but so far I only know how to use ranges:
p => c(1:4)
call printer(p)
write(*,*)
p => c(2)%b(3:6)
call printer(p)
write(*,*)

end program
编辑:
为了记录在案,我现在通过使用包括指针在内的派生类型数组并稍微更改调用子例程解决了这个问题。

指针关联(例如
pointer1=>array1(vector_下标)
。Fortran 2008标准第7.2.2节不允许这样做:

R733指针分配stmt是数据指针对象[(边界规范列表)]=>数据目标

还有两种其他形式,但它们与您的使用不匹配,也不会改变结果。进一步阅读:

R737数据目标是变量
C724(R737)变量应具有TARGET或POINTER属性,且不得为带有矢量下标的数组部分

这就是您无法执行正在尝试的指针关联的原因。但是,您可以解决此问题并使用指针分配。请参阅以下代码:

n_k = 3
k = [((j+1)*2,j=1,n_k)] ! a vector subscript
p => a(k)               ! NOT OK. Violates C724
allocate(p(n_k))        ! Associate your pointer this way
p = a(k)                ! This is OK. 
write(*,*) p
这将产生(包装在示例程序中):

这将
p
分配为适当的大小,然后从
a
分配一个向量下标。这绕过了将
p
a
映射直接关联的问题。此代码段假定变量是根据示例代码声明和初始化的。这表明可以分配一个向量subsc指向指针的数组,但仅指向已关联的指针,而不是在关联期间


正如Q的一条评论所指出的,如果你有一个常规的步幅,你可以直接建立指针关联。对于你的第一个测试用例,这将是等效的,并且可以工作:

p => a(4:2:8)            ! Allocation to a strided array is allowed
然而,如果你有一个不规则的向量下标,那么这个答案中的方法就是你需要用来完成指针关联的方法


您可以使用的另一个方法是将指针和映射传递给一个过程。

program test
  implicit none

  integer, parameter :: nx = 10, nx_m = 3
  integer,dimension(nx_m) :: x_map
  integer :: i
  real, dimension(nx),target :: a
  real, dimension(:), pointer :: p

! initialize array
  a = [(real(i*2),i=1,10)]
  write (*,'(10(f5.1 x))') a

!define a map
  x_map = [1, 9, 4]

! associate pointer
  p => a

  call print_map(p, x_map)

contains

subroutine print_map(apointer, map)
  implicit none
  real, dimension(:), pointer :: apointer
  integer, dimension(:) :: map

  write (*,*) apointer(map)

   end subroutine print_map
end program test
在这种情况下,
p
“知道”关于
a
a
中元素的映射可以在调用者中计算。而不是将(
=>
p
关联为
a
的映射(这是无法完成的),
p
关联到
a
,并将映射随它一起传递

此代码生成以下输出:

% ./ptrtest3                       
2.0   4.0   6.0   8.0  10.0  12.0  14.0  16.0  18.0  20.0
2.00000000       18.0000000       8.00000000 

您也可以通过添加步幅来关联指针,例如
p=>a(4:8:2)
,然后
p
将指向数组
a
8
部分,步幅为
2
。当然,你的地图必须有规律地步幅。地图是任意的,在输入时定义的。谢谢你的回答。但是
p
只是一个规则数组,而不是指针,因此不是指针“知道”它的目标。@PeMa这是真的。除非你有一个均匀的步幅并且做
p=>a(1:2:10)
你将无法用任意的地图完成你想要的。+1,但是对于答案的第二部分(没有得到第一部分与之相关的东西)。对于任意贴图,只需像您已经在做的那样使用索引数组,然后您可以将其与数据一起传递以进行打印,或者创建一个类似于此答案的副本(尽管我建议不要使用指针)@steabert第一部分只是解释为什么他不能使用映射将数组中的任意元素分配给指针。我喜欢包括标准的相关部分,而不是说“你不能这样做,因为它不在标准中。”“@casey:看来我只需要重读问题的第一部分。OP说你不能做
array2=[(array1(k(j)),j=1,size(k,1))]
有一个指针,但这是不正确的,只要指针是关联的,你就完全可以做到。但现在我明白了,他是说你不能做
array2=>…
这就是你对他的问题的理解。所以,在我看来,答案很奇怪,因为它证实了他所说的。你答案中的第一句应该是be:你不能做
array2=>…
,因为在我看来“this”似乎指的是
array2=…
。我希望这是有意义的?:)
% ./ptrtest3                       
2.0   4.0   6.0   8.0  10.0  12.0  14.0  16.0  18.0  20.0
2.00000000       18.0000000       8.00000000