- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
Link kopiert
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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!)
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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")) .....
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Please don't use nonstandard syntax such as "logical*4". Just "logical" would work fine here.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Effectively,
if (index(str,"s").eq.2) ...
will do the job.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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"?
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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"?
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
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.
- RSS-Feed abonnieren
- Thema als neu kennzeichnen
- Thema als gelesen kennzeichnen
- Diesen Thema für aktuellen Benutzer floaten
- Lesezeichen
- Abonnieren
- Drucker-Anzeigeseite