- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a subroutine splits_str_to_int (s, delim, t1, t2, t3, t4, t5), where t2, t3, t4, and t5 are optional. I am creating a wrapper around it. When using optional arguments in the wrapper subroutine, do I need to check whether the arguments are present first?. <code>Subroutine splits & ( & s, delim, & t1, t2, t3, t4, t5, t6, t7, t8, & pos & ) Character (len=*), Intent (in) :: s, delim Character (len=*), Intent (in), Optional :: pos Integer, Intent (out) :: t1 Integer, Intent (out), Optional :: t2, t3, t4, t5, t6, t7, t8 Integer :: nf If (Present (t2)) Then Call splits_str_to_int (s, delim, t1, t2) Else If (Present (t3)) Then Call splits_str_to_int (s, delim, t1, t2,t3) Elre If (Present (t4)) Then Call splits_str_to_int (s, delim, t1, t2, t3, t4) Else If (Present (t5)) Then Call splits_str_to_int (s, delim, t1, t2, t3, t4, t5) End If </code>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To the extent that optional arguments that may or may not be present can be passed along as actual arguments to other routines, yes. However, there are certain rules regarding optional arguments that your code does not satisfy. You have to provide explicit interfaces, and use the keyword=value form when arguments cannot be associated by position in the argument list.
Try the following fixed-up version. In the last call to "splits", "pos=pos" could be replaced by just "pos".
Program Test implicit none integer s, delim,sn,pos,t1,t2,t3,t4,t5,t6,t7,t8,t9 Call splits (s, delim, sn=sn) Call splits (s, delim, sn=sn, pos=pos) Call splits (s, delim, t1, t2) Call splits (s, delim, t1, t2, pos=pos) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9, pos=pos) CONTAINS Subroutine splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, sn, pos) implicit none Integer, Optional :: t1, t2, t3, t4, t5, t6, t7, t8, sn, pos Integer :: s,delim Call splits_str_to_str (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, pos=pos) End Subroutine Subroutine splits_str_to_str (s, delim, s1, s2, s3, s4, s5, s6, s7, s8, sn, pos) implicit none Integer, Optional :: s1, s2, s3, s4, s5, s6, s7, s8, sn, pos integer :: s,delim write(*,*)' In Splits_str_to_str',present(s1),present(s2),present(s3), & present(s4),present(s5),present(s6),present(s7),present(s8), & present(sn),present(pos) End Subroutine End Program
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you are confident that your subprogram code will reference optional arguments only if they are present, no, you need not check. If you have, say, three optional arguments and all three will be present if the first one is, it is sufficient to check only for the presence of the first. On the other hand, if you reference an optional argument that is not present, your program is almost sure to crash.
If you can organize your code such that the number of instances of IF(PRESENT())THEN...ENDIF are few, yet sufficient to ensure that no optional argument is referenced if not present, you would have reached a good compromise.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That means that I will be assuming some things, such as requirements of which optional arguments will be present?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Correct. Essentially, you make an agreement with yourself as to which groups of optional arguments will be present during various calls. If this is either inconvenient or hard to adhere to, you can use IF (PRESENT...), but avoid putting that inside DO loops.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Would I be able to have the following code? Program Test Call splits (s, delim, sn) Call splits (s, delim, sn, pos) Call splits (s, delim, t1, t2) Call splits (s, delim, t1, t2, pos) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9, pos) End Program Subroutine splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, sn, pos) Integer, Optional :: s1, s2, s3, s4, s5, s6, s7, s8, sn, pos Call splits_str_to_str (s, delim, s1, s2, s3, s4, s5, s6, s7, s8, pos) End Subroutine Subroutine splits_str_to_str (s, delim, s1, s2, s3, s4, s5, s6, s7, s8, sn, pos) Integer, Optional :: s1, s2, s3, s4, s5, s6, s7, s8, sn, pos End Subroutine
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To the extent that optional arguments that may or may not be present can be passed along as actual arguments to other routines, yes. However, there are certain rules regarding optional arguments that your code does not satisfy. You have to provide explicit interfaces, and use the keyword=value form when arguments cannot be associated by position in the argument list.
Try the following fixed-up version. In the last call to "splits", "pos=pos" could be replaced by just "pos".
Program Test implicit none integer s, delim,sn,pos,t1,t2,t3,t4,t5,t6,t7,t8,t9 Call splits (s, delim, sn=sn) Call splits (s, delim, sn=sn, pos=pos) Call splits (s, delim, t1, t2) Call splits (s, delim, t1, t2, pos=pos) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9) Call splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, t9, pos=pos) CONTAINS Subroutine splits (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, sn, pos) implicit none Integer, Optional :: t1, t2, t3, t4, t5, t6, t7, t8, sn, pos Integer :: s,delim Call splits_str_to_str (s, delim, t1, t2, t3, t4, t5, t6, t7, t8, pos=pos) End Subroutine Subroutine splits_str_to_str (s, delim, s1, s2, s3, s4, s5, s6, s7, s8, sn, pos) implicit none Integer, Optional :: s1, s2, s3, s4, s5, s6, s7, s8, sn, pos integer :: s,delim write(*,*)' In Splits_str_to_str',present(s1),present(s2),present(s3), & present(s4),present(s5),present(s6),present(s7),present(s8), & present(sn),present(pos) End Subroutine End Program
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should review your original logic as it presents some problems.
The second and subsequent if tests are only possible if t2 is NOT present, which implies that all your subsequent calls, which include t2 will fail.
If (Present (t2)) Then
Call splits_str_to_int (s, delim, t1, t2)
Else If (Present (t3)) Then
Call splits_str_to_int (s, delim, t1, t2,t3) ! Present (t2) = .false.
An alternative may be to provide a sufficiently large vector for ti's and a count of how many ti's are returned.
Isn't this count a function of the content of "s", rather than the supplied t1, t2,...
John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page