How to declare a variable mid-routine in Fortran

后端 未结 4 1127
难免孤独
难免孤独 2020-12-07 03:56

I would like to create an array with a dimension based on the number of elements meeting a certain condition in another array. This would require that I initialize an array

相关标签:
4条回答
  • 2020-12-07 04:03

    You can use allocatable arrays for this task:

    subroutine example(some_array)
    
    real             :: some_array(50)
    real,allocatable :: new_array(:)
    integer          :: i, element_count, status
    
    element_count = 0
    do i=lbound(some_array,1),ubound(some_array,1)
      if ( some_array(i) > 0 ) then
        element_count = element_count + 1
      endif
    enddo
    
    allocate( new_array(element_count), stat=status )
    if ( status /= 0 ) stop 'cannot allocate memory'
    
    ! set values of new_array
    
    end subroutine
    
    0 讨论(0)
  • 2020-12-07 04:09

    Your questions isn't about initializing an array, which involves setting its values.

    However, there is a way to do what you want. You even have a choice, depending on how general it's to be.

    I'm assuming that the element_count means to have a some_array(i) in that loop.

    You can make new_array allocatable:

    subroutine example(some_array)
      real some_array(50)
      real, allocatable :: new_array(:)
    
      allocate(new_array(COUNT(some_array.gt.0)))
    end subroutine
    

    Or have it as an automatic object:

    subroutine example(some_array)
      real some_array(50)
      real new_array(COUNT(some_array.gt.0))
    end subroutine
    

    This latter works only when your condition is "simple". The allocatable case is much more general, such as when you want to use the full loop rather than the count intrinsic.

    In both of these cases you meet the requirement of having all the declarations before executable statements.

    [As a side-note, under Fortran 2008 the block construct allows automatic objects even after executable statements.]

    0 讨论(0)
  • 2020-12-07 04:13

    Try this

    real, dimension(50) :: some_array
    real, dimension(:), allocatable :: other_array
    integer :: status
    ...
    allocate(other_array(count(some_array>0)),stat=status)
    

    at the end of this sequence of statements other_array will have the one element for each element of some_array greater than 0, there is no need to write a loop to count the non-zero elements of some_array.

    Following @AlexanderVogt's advice, do check the status of the allocate statement.

    0 讨论(0)
  • 2020-12-07 04:19

    You need to use an allocatable array (see this article for more on it). This would change your routine to

    subroutine example(input_array,output_array)
    
      real,intent(in) :: input_array(50) ! passed array of known dimension
      real, intent(out), allocatable :: output_array(:)
      integer :: element_count, i
    
      element_count = 0
      do i=1,50
        if (some_array.gt.0) element_count = element_count+1
      enddo
    
      allocate(output_array(element_count))
    
    end subroutine
    

    Note that the intents may not be necessary, but are probably good practice. If you don't want to call a second array, it is possible to create a reallocate subroutine; though this would require the array to already be declared as allocatable.

    0 讨论(0)
提交回复
热议问题