- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Since I didn't find any part of the standard stating out sequence of judging parallel conditions, I would like to ask if anyone has even met the situation like:
function Test(str)
implicit none
character(*), intent(in) :: str
if(LEN(str) >=2 .AND. str(2:2) == 's')then
! do something...
end if
end function Test
In the if statement above, there are two conditions. If the dummy argument str we passed in was just a single character assume 'a', there is going to be an error with ivf compiler as condition str(2:2)=='s' is referring to index number 2 of 'a' which simply doesn't exist. So in Fortran, is it true that conditions within a judging statement are all be judged every time of execution ? In other words no left-to-right judging sequence ? About this case I See difference in C# while since condition LEN(str)>=2 is false, the if block will be skipped and, no matter true or false the second condition is, it is not ever judged so it's legal to write these conditions together, but not in Fortran. Appreciate any explanation.
- Balises:
- Intel® Fortran Compiler
Lien copié
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Fortran and C/C++/C# have different rules for expression evaluation. Fortran allows the compiler to evaluate any logically equivalent expression to any degree of completeness. There is no strict left-to-right nor short-circuiting. It's a classic error Fortran programmers have made for decades - sometimes it works the way they want and they think that's what the language says, and then they change compilers or even versions and the order changes.
The correct solution is to use nested IF-THEN.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
This goes to the often discussed topic of "short-circuit evaluation". There are a number of posts in our Fortran forums discussing what compilers are permitted to do within the Standard.
To your questions, no not all conditions are judged at execution and no left-to-right evaluation is guaranteed. Refer to Dr. Fortran and "The Dog That Did Not Bark"
Here's a couple of other posts that offer related discussion and details.
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/499227
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/282534
(Posting although I see the Doctor himself has replied - Thank you Steve!)
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
If you do not like (want) nested IF-THEN blocks, then write an Fortran acceptable IF statement
if(LEN(str) >=2 .AND. str(MIN(LEN(str),2):MIN(LEN(str),2)) == 's') then
But then I think you will agree that nested IF-THEN blocks will be clearer (and faster).
Jim Dempsey
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
A solution is to create a specific function that will make the code clearer. For example something like that:
logical*4 function test_2nd_char(str,char)
character(*), intent(in) :: str,char
test_2nd_char=.false.
if (len(str).le.2) return
if (str(2:2).ne.char(1:1)) return
test_2nd_char=.true.
end function
if (test_2nd_char(str,"s")) .....
Or more generic :
logical*4 function match(str,pattern)
character(*), intent(in) :: str,pattern
match=.false.
if (len(str).lt.len(pattern)) return
do i=1,len(pattern)
if (pattern(i:i).ne."*".and.str(i:i).ne.pattern(i:i)) return
enddo
match=.true.
end function
if (match(str,"*s")) .....
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Please don't use nonstandard syntax such as "logical*4". Just "logical" would work fine here.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Steve Lionel (Ret.) wrote:
Please don't use nonstandard syntax such as "logical*4". Just "logical" would work fine here.
Indeed; I would also suggest anyone considering any such "special" functions should first review what the Fortran standard offers as intrinsic procedures; INDEX, SCAN, VERIFY in this instance.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Effectively,
if (index(str,"s").eq.2) ...
will do the job.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
That's a very good solution on this case, thanks a lot.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
@Vautier, Gilles,
"will do the job" - how? What if str is "ss"?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Blane J. wrote:
Quote:
Vautier, Gilles wrote:
Effectively,
if (index(str,"s").eq.2) ...will do the job.
That's a very good solution on this case, thanks a lot.
@Blane J.,
Did you check how your expected IF construct would function if you followed Steve's correct advice in Message #2 versus what you would get if you follow this latest one with the INDEX intrinsic? What should happen if str equals "ss"?
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
FortranFan wrote:
What should happen if str equals "ss"?
So the best solution is to write a user function.as I show in a precedent post.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
LOL. Like many things in programming there are many possible solutions, in this case the 'best' solution probably depends if this test is done in lots of places or just one, in the former case my personal preference would be a user function (less code easier to maintain), in the latter case a nest IF as it is more immediately apparent what the program logic is without having to find a and look at a function.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
or...
module mod_test
contains
logical function Test(str)
implicit none
character(*), intent(in) :: str
Test = .false. ; if(LEN(str) >=2) Test = (str(2:2) == 's')
end function Test
end module mod_test
program ifif
use mod_test
implicit none
print *, Test('x')
print *, Test('xx')
print *, Test('xs')
end program ifif
Jim Dempsey
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
FortranFan wrote:
@Blane J.,
Did you check how your expected IF construct would function if you followed Steve's correct advice in Message #2 versus what you would get if you follow this latest one with the INDEX intrinsic? What should happen if str equals "ss"?
Oops, that's a problem. so as suggested, a user function to handle the evaluation process should be the best anyway, thanks all again above.
- S'abonner au fil RSS
- Marquer le sujet comme nouveau
- Marquer le sujet comme lu
- Placer ce Sujet en tête de liste pour l'utilisateur actuel
- Marquer
- S'abonner
- Page imprimable