24小时热门版块排行榜    

CyRhmU.jpeg
查看: 2558  |  回复: 12

qingkonggzc

银虫 (小有名气)

[交流] fortran动态数组大小分配问题(allocatable)?已有2人参与

各位大神,我定义了一个动态数组type(sta_information),allocatable::sta_info(,在给sta_info分配大小的时候遇到了问题,我有一个循环,想让这个数组的大小随着循环变化可以吗?还是必须要开始时就指定一个较大的能放下所有数据/字符串的数组?因为我把所有数据放进去之后要进行从A到Z的排序,如果数组太大有空的会不会影响排序?
就是第一个循环大小分配55,到第二个循环的时候让他大小变成100,第三个循环的时候大小变成200(也就是分别产生55,45,100个数据),因为不知道数据总量,不想刚开始就把大小设置的比较大,比如allocate(sta_info(1000))等,请问这个可以如何处理,谢谢~~~
回复此楼

» 猜你喜欢

» 本主题相关价值贴推荐,对您同样有帮助:

已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
回帖支持 ( 显示支持度最高的前 50 名 )

pippi6

铁杆木虫 (著名写手)

工程和科学数值计算咨询


小木虫: 金币+0.5, 给个红包,谢谢回帖
subroutine DynamicArray
  implicit none
  real*8, allocatable, dimension( :: sta_info
  integer :: i,n=20,j

  do i=1,n
     allocate(sta_info(i))
     
     do j=1,i
        sta_info(j)=j
     end do
     print*,' i=',i,' sizeof(sta_info)=',sizeof(sta_info)
     deallocate(sta_info)
  end do
end subroutine DynamicArray
3楼2015-05-27 13:14:14
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

浔荆

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
引用回帖:
11楼: Originally posted by qingkonggzc at 2015-05-28 20:56:39
是不是必须要先定义一个大的数组,这样才能
sta_info(0)=sta_info(0)+1
     sta_info(sta_info(0))=....     !在这里写入新数据
这样用呢?能不能就让它占多大就定义多大的大小?
我出错的地方时第二个循环的 ...

显然不能啊。。。
fortran语法是比较严格的,要么定义成固定大小的数组,要么定义成动态数组。但不管是哪个,数组在用的时候都有一个确定的长度。
你可以随时deallocate然后再allocate,但这样的计算效率是比较低的。
定义一个0:1000的数组只是多占用一些内存而已,由于sta_info(0)已经标明了数组大小,实际排序的时候也只排序1:sta_info(0)个元素,效率上并没有降低。
如果实在是内存不够,需要控制内存开销的话,可以选择性的deallocate再allocate数组。例如一开始定义为0:100,添加新元素时先判断数组是否已经满了,不够用时,再重新定义成0:200,还不够用就0:400,以此类推。
以下是示意性代码
subroutine extend_array()
allocatable,integer*4::sta_info_dummy(:)

if(sta_info(0)>=sizeof(sta_info))then
   allocate(sta_info_dummy(sta_info_size)) !定义中间数组保存数据
   sta_info_dummy=sta_info
   deallocate(sta_info)                         !扩张数组大小
   allocate(sta_info(sta_info_dummy(0)*2))     
   sta_info(1:sta_info_size)=sta_info_dummy   !恢复数据
endif
end subroutine extend_array

» 本帖已获得的红花(最新10朵)

12楼2015-05-29 14:16:12
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
普通回帖

浔荆

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
我也常遇到这样的问题,一般我是通过以下方案解决的。
定义一个很大的数组,如sta_info(0:1000)。
之所以定义成sta_info(0:1000)而非sta_info(1:1000),并不是因为我习惯了C语言里的数组默认下标从0开始。实际上,这里的sta_info(0)和其他元素不一样,它是用来记录整个数组的有效大小的。
例如,我们在第一个循环给元素0:55赋值,其他的元素用不到,可以这么实现:
allocate(sta_info(0:1000))
sta_info=-10000                   !初始化为一个不常见的数,方便调试
sta_info(0)=55                     !确定你需要的数组大小
do i=1,sta_info(0)
     sta_info(i)=.....
enddo

简单来说,就是先分配足够的大小,但另外定义一个变量来描述它的实际大小。这样一来避免了数组大小变化的时候,需要频繁的allocate和deallocate。另一方面又可以避免数组太大而带来的速率降低。(排序这样的数组操作,只需要对1:sta_info(0)这些元素进行即可)
2楼2015-05-27 08:19:38
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

qingkonggzc

银虫 (小有名气)

引用回帖:
2楼: Originally posted by 浔荆 at 2015-05-27 08:19:38
我也常遇到这样的问题,一般我是通过以下方案解决的。
定义一个很大的数组,如sta_info(0:1000)。
之所以定义成sta_info(0:1000)而非sta_info(1:1000),并不是因为我习惯了C语言里的数组默认下标从0开始。实际上, ...

你好,谢谢。
首先这样和直接定义一个较大的数组,然后依次把数据/字符串写进去效果应该是一样的吧,就是有多少数据写多少空间的,剩下的还是空的,然后对其进行排序?这个直接把总共有多少数据计算出来,然后对这1-n个数据进行排序后面的没有影响吗?还是把这1-n个数据提取出来放到一个新的数组里面?
4楼2015-05-27 19:23:58
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

qingkonggzc

银虫 (小有名气)

引用回帖:
3楼: Originally posted by pippi6 at 2015-05-27 13:14:14
subroutine DynamicArray
  implicit none
  real*8, allocatable, dimension( :: sta_info
  integer :: i,n=20,j

  do i=1,n
     allocate(sta_info(i))
     
     do j=1,i
        sta_info(j)=j ...

你好,谢谢你,我的这个是只能在这一个循环结束之后才能读出来第二个循环该有多少个数据的,也不能在开始的时候就给他一个大小值啊?你这还是构造一个中间数组用来保存每一个循环的数据,再把这些数据汇总到一个数组里面去,类似于MATLAB里面的矩阵合并C=[a b]?Fortran里面可以这样合并吗?
5楼2015-05-27 19:38:26
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

浔荆

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
引用回帖:
4楼: Originally posted by qingkonggzc at 2015-05-27 19:23:58
你好,谢谢。
首先这样和直接定义一个较大的数组,然后依次把数据/字符串写进去效果应该是一样的吧,就是有多少数据写多少空间的,剩下的还是空的,然后对其进行排序?这个直接把总共有多少数据计算出来,然后对这 ...

对,是一样的。不一样的只是你可以针对非空元素进行操作而已。
假设有n个有效数据,剩余的全是空值。那么,你排序只需要对这n个数据排序就行了,不需要提取出来也不需要中间数组。直接操作部分数组就行。
你可以把排序子程序写成这样:
subroutine sort(array,n)
integer*4 array(0:1000)
integer*4 n              !只有1~n元素是有效的

......                        !对1~n号元素排序

end subroutine sort

然后调用时,直接call sort(sta_info,sta_info(0))就行了。
这个原理和字符串的原理是类似的,定义一个长度1000的字符串,其实际长度为1001,其中有一位是用于记录字符串有效长度的,有效长度之外全部是空格。
6楼2015-05-28 08:13:16
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

qingkonggzc

银虫 (小有名气)

引用回帖:
6楼: Originally posted by 浔荆 at 2015-05-28 08:13:16
对,是一样的。不一样的只是你可以针对非空元素进行操作而已。
假设有n个有效数据,剩余的全是空值。那么,你排序只需要对这n个数据排序就行了,不需要提取出来也不需要中间数组。直接操作部分数组就行。
你 ...

你好,我还是有点不明白只对1~n号元素进行排序的意思,虽然我想要的是这个结果,是对n号元素排序之后新放到一个数组里面还是在原来的数组里面,最后面的还是空?
allocate(sta_info(0:1000))
sta_info=-10000                   !初始化为一个不常见的数,方便调试
sta_info(0)=55                     !确定你需要的数组大小
do i=1,sta_info(0)
     sta_info(i)=.....
enddo

sta_info=-10000是相当于给这数组一个unit嘛?不太明白这个初始化的意思。。
sta_info(0)=55                     !确定你需要的数组大小
do i=1,sta_info(0)
     sta_info(i)=.....
enddo
这个当把第二个循环的大小确定为100的时候,怎么样能使它接着在sta_info后面写45个数据,这样应该会使它覆盖掉前一循环的数据吧?还是把大小也存放到一个数组里面,每次循环do从sta_num(i-1)~sta_num(i)?
7楼2015-05-28 09:48:17
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

qingkonggzc

银虫 (小有名气)

引用回帖:
2楼: Originally posted by 浔荆 at 2015-05-27 08:19:38
我也常遇到这样的问题,一般我是通过以下方案解决的。
定义一个很大的数组,如sta_info(0:1000)。
之所以定义成sta_info(0:1000)而非sta_info(1:1000),并不是因为我习惯了C语言里的数组默认下标从0开始。实际上, ...

你好,这是我程序里面的一部分,但是这样在第二个循环的时候就会触发断点,这样的话,存储大小会溢出?如果我直接把大小设置为1000,就不会触发断点
integer::sta_array_size=0
integer::day_sta_num=0
sta_array_size = sta_array_size + day_sol_sum%sta
allocate(sta_info(sta_array_size))
do j=1,day_sol_sum%sta,1            
       read(101,'(a)',end=200) sum_line
       sta_info(day_sta_num+j)%sta_name=sum_line(2:5)        
       sta_info(day_sta_num+j)%phase_RMS=sum_line(10:13)   
       sta_info(day_sta_num+j)%weekday=doy-start_doy+1      
   end do
day_sta_num = day_sol_sum%sta + day_sta_num
8楼2015-05-28 10:58:38
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

浔荆

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
引用回帖:
7楼: Originally posted by qingkonggzc at 2015-05-28 09:48:17
你好,我还是有点不明白只对1~n号元素进行排序的意思,虽然我想要的是这个结果,是对n号元素排序之后新放到一个数组里面还是在原来的数组里面,最后面的还是空?
allocate(sta_info(0:1000))
sta_info=-10000    ...

记录大小的sta_info(0)可以动态化,写新数据时,从sta_info(0)位元素开始写就行了,例如你要在数组尾部写入45个新数据时,可以这么操作:

do i=1,45   !45为你要写入的新数据个数
     sta_info(0)=sta_info(0)+1
     sta_info(sta_info(0))=....     !在这里写入新数据
enddo
循环结束时,新的数据都储存在数组的尾部,sta_info(0)从原来的55变为了100
9楼2015-05-28 11:45:15
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

浔荆

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
引用回帖:
8楼: Originally posted by qingkonggzc at 2015-05-28 10:58:38
你好,这是我程序里面的一部分,但是这样在第二个循环的时候就会触发断点,这样的话,存储大小会溢出?如果我直接把大小设置为1000,就不会触发断点
integer::sta_array_size=0
integer::day_sta_num=0
sta_ar ...

在哪行断掉的?报错信息是什么?
10楼2015-05-28 11:49:08
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 qingkonggzc 的主题更新
普通表情 高级回复(可上传附件)
信息提示
请填处理意见