elfsummer
elfsummer

Reputation: 167

how to read in indefinite # of input parameters in a function/subroutine in Fortran?

The following fortran code will calculate the area of a circle or a rectangle according to user's input. If there is only one input floating point then it will calculate the area of a circle while if there are two then it will return the area of a rectangle. Currently, I do this by user typing 1 or 2 at first. However, I would like to know if there are direct ways of reading in indefinite # of input parameters in fortran. Please do offer your wisdom. I appreciate it!

module MA
  implicit none

interface area
  module procedure area_circ  ! calculate the area of circles
  module procedure area_rec   ! rectangles
end interface

contains
  real function area_circ(a)
  implicit none
  real, intent(in) :: a
  real, parameter :: pi=3.14159
  area_circ = pi*a**2
  write(*,"('Area of circle = ',F6.2)") area_circ
  return
end function area_circ

real function area_rec(a,b)
  implicit none
  real, intent(in) :: a,b
  area_rec=a*b
  write(*,"('Area of rectangle = ',F6.2)") area_rec
  return
end function area_rec

end module MA

program hw1101
  use MA
  implicit none
  real :: a,b,S
  integer :: i

  write(*,*) 'Please type # of parameters: '
  read(*,*) i
  if(i==1) then
    write(*,*) "Please type one parameter: "
    read(*,*) a
    S=area(a)
  else if (i==2) then
    write(*,*) "Please type two paramters: "
    read(*,*) a,b
    S=area(a,b)
  else
    write(*,*) "Other functions under construction..."
  end if

  stop
end program hw1101

Upvotes: 0

Views: 173

Answers (2)

High Performance Mark
High Performance Mark

Reputation: 78314

An up-to-date Fortran compiler provides a number of intrinsic routines for handling command line arguments. You can use the function COMMAND_ARGUMENT_COUNT to get the number provided when you execute the program, then read them one by one. Perhaps something like this:

  CHARACTER(len=16) :: arg
  REAL, DIMENSION(4) :: arguments
  ...
  DO ix = 1, COMMAND_ARGUMENT_COUNT()
     CALL GET_COMMAND_ARGUMENT(ix,arg)
     READ(arg,*) arguments(ix)
  END DO

Note that the subroutine GET_COMMAND_ARGUMENT returns a character variable through the second argument (which I've called arg). It has other, optional, arguments so you might want to check some documentation.

There's nothing wrong with your current approach for determining which area function to call but if you wanted to you could also write an area function which takes optional arguments. Here's an example:

  REAL FUNCTION area(a,b)
    REAL, INTENT(in) :: a
    REAL, INTENT(in), OPTIONAL :: b
    IF (.NOT.PRESENT(b)) THEN
       area = 3.14159*a*a
    ELSE
       area = a*b
    END IF
  END FUNCTION area

which should give you the general idea. The attribute OPTIONAL and the intrinsic logical function PRESENT are what you need for routines with optional argument. I think the approach you've already taken is actually better.

Upvotes: 3

yeonpil.net
yeonpil.net

Reputation: 168

real a, b, s
character(len=20) :: string_in
integer istat
read(*, '(a)') string_in
read(string_in, *, iostat=istat) a, b
if (istat /= 0) then
    read(string_in, *, iostat=istat) a
    if (istat == 0) s = area (a)
else
    s = area (a, b)
end if

Upvotes: 0

Related Questions