View previous topic :: View next topic |
Author |
Message |
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Mon Jan 08, 2018 2:49 pm Post subject: Using centre@ function |
|
|
Is there a "correct" way to wrap the Centre@ function in another function using Fortran 90/95? Centre@ returns a string of length determined by the assignment statement which cannot easily be replicated in code (at least I can't find an obvious way). Many years ago I vaguely remember a newsgroup question on a similar topic in which one of the elder statesmen of Fortran said that this sort of this was not within the scope (or desirability) of the F90 standard.
Before anyone asks, I am trying to create a portability wrapper so the main code can be compiled in various compilers including FTN95. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Mon Jan 08, 2018 3:39 pm Post subject: |
|
|
One lives and learns - I never knew such a function existed.
Surely it is a matter of positioning the input string STRING in a character variable of length LW (as in FTN95.CHM) by (LW-LEN_TRIM(STRING))/2 from the start of the output string? (and therefore not difficult).
Eddie |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Mon Jan 08, 2018 4:01 pm Post subject: |
|
|
Also I suspect that the length of the result is determined by the declaration of CENTRE@ and not by an assignment statement. For example
Code: | CHARACTER (LEN=80) CENTRE@ |
|
|
Back to top |
|
|
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Mon Jan 08, 2018 5:44 pm Post subject: Re: |
|
|
LitusSaxonicum wrote: | One lives and learns - I never knew such a function existed.
Surely it is a matter of positioning the input string STRING in a character variable of length LW (as in FTN95.CHM) by (LW-LEN_TRIM(STRING))/2 from the start of the output string? (and therefore not difficult).
Eddie |
All very well, but how do you define the return type of the function if you don't know the length of the string being assigned to? |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Mon Jan 08, 2018 5:49 pm Post subject: |
|
|
I am assuming that somewhere in your code there is a declaration of the form
Code: | CHARACTER (LEN=80) CENTRE@ |
|
|
Back to top |
|
|
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Mon Jan 08, 2018 5:52 pm Post subject: Re: |
|
|
PaulLaidler wrote: | I am assuming that somewhere in your code there is a declaration of the form
Code: | CHARACTER (LEN=80) CENTRE@ |
|
No. I am writing a wrapper function which doesn't know the length of the string being passed to Centre@. That is the problem. |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7927 Location: Salford, UK
|
Posted: Mon Jan 08, 2018 6:19 pm Post subject: |
|
|
Perhaps the easiest solution is to use Eddie's approach. |
|
Back to top |
|
|
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Mon Jan 08, 2018 7:05 pm Post subject: Re: |
|
|
PaulLaidler wrote: | Perhaps the easiest solution is to use Eddie's approach. |
"Eddie's approach" didn't seem to answer the problem of not knowing the length of the input string at compile time. I tried several different ways to copy the runtime length of the input string dummy argument to the function return length, but none of them worked. I was hoping someone could come up with a solution.
My current "easiest" solution is to replace Centre@ function with a F90/F95 portable subroutine that does in code what Centre@ does intrinsically. It is a bit messier to call as you need 2 lines of code where the function does the same in one line, but it does at least do what I want. I guess the Centre@ function is a bit "too good to be true" and can't be replicated in a portable way.
Last edited by PaulHolden on Thu Jan 11, 2018 11:58 pm; edited 1 time in total |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1217 Location: Morrison, CO, USA
|
Posted: Tue Jan 09, 2018 12:37 am Post subject: |
|
|
Is the single statement use of a function *REQUIRED* to happen, or can you use a subroutine call?
Something of the form of:
Code: |
CALL CENTRE_CALL(OLD_STRING,NEW_CENTERED_STRING)
|
should work just fine, and can easily be made size independent in the subroutine.
Code: |
USE MSWIN
CHARACTER*20:: ABCD="THIS IS A TEST"
CHARACTER(LEN=LEN(ABCD)*2) DEFG
CHARACTER(LEN=LEN(DEFG)),EXTERNAL:: CENTRE@
CHARACTER*10:: OLD='OLDDATA'
CHARACTER*20:: NEWEST=' '
DEFG = CENTRE@(ABCD,LEN(DEFG))
PRINT *,'"',ABCD,'"'
PRINT *,'"',DEFG,'"'
CALL CENTRE_CALL(OLD,NEWEST)
STOP
END
SUBROUTINE CENTRE_CALL(OLD,NEWEST)
CHARACTER*(*) OLD
CHARACTER*(*) NEWEST
CHARACTER(LEN=LEN(NEWEST)),EXTERNAL:: CENTRE@
INTEGER*2:: I
I=LEN(NEWEST)
NEWEST=' ' ! THIS MUST BE HERE, BUT SHOULDN'T NEED TO BE
NEWEST = CENTRE@(OLD,I)
PRINT *,'"',OLD,'"'
PRINT *,'"',NEWEST,'"'
RETURN
END
|
Setting NEWEST to blank should not have to be there (it is initialized in the MAIN routine), but without it, things don't work right.
Also, having to use I works, but replacing it with int(len(newest),2) to set the type properly didn't work. |
|
Back to top |
|
|
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Thu Jan 11, 2018 8:08 pm Post subject: |
|
|
Thanks wahorger. The subroutine isn't as convenient as a function but it seems to be the only solution. |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Fri Jan 12, 2018 7:38 am Post subject: |
|
|
does %cn instead of centre@ present a possible preferable solution option ? |
|
Back to top |
|
|
PaulHolden
Joined: 08 Jan 2018 Posts: 6
|
Posted: Fri Jan 12, 2018 7:52 pm Post subject: Re: |
|
|
John-Silver wrote: | does %cn instead of centre@ present a possible preferable solution option ? |
The idea is to make a portable function and %cn is certainly not that. I can easily reproduce the centering in subroutine code and avoid centre@ altogether, but not as a function. |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Sun Jan 14, 2018 1:43 pm Post subject: |
|
|
I see that Paul, and that people have proposed solutions to circumvent the use of centre@, but the original question was worded as when you were still trying to use centre@, which is an ftn95 fucntion right, hence maybe equally 'incompatible' as centre@ - maybe.
So I just thought maybe %cn could actually be used with maybe no compatability problems in terms of declarations.
Clearwin is 'ported' to be useable with other fortran compilers so is useable in that sense.
Isn't .NET the politically correct route to take for platform independent (i.e. compatability) needs ?
The people at SIMPLEPLOT apparently got a case working with their code attached. Maybe that 's a route to consider/pursue in the longer term.
From what's written in the case-study concerning Simpleplot (in the documentation cěsection on website) Silverfrost wer very helpful at the time in helping them get it up and running. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Sun Jan 14, 2018 4:53 pm Post subject: |
|
|
If I am right (and I concede that it is about 20 years since I last worked with Assembler, so I could be wrong), then all a FUNCTION returns is the address to its result on the stack. Moreover, the result is 'forgotten' immediately after the assignment or WRITE in which the function is invoked when the stack is cleaned up.
Hence, so long as the return address is mangled to point to the string of length LW with the input STRING centered in it, then that sequence of characters ought to be picked up in the calling routine and copied (or used) for that one time. It doesn't matter where in RAM that temporary copy resides, surely, and it could reside somewhere where it was ephemeral, i.e. allocated dynamically, if you so wish.
I assume that FTN95 reserves a long enough contiguous sequence of bytes at compilation by finding the longest declaration of the length of CENTRE@ (viz. FTN95.CHM's example call), the address of which is known to it, to Paul, and all the other folk at Silverfrost who understand such things, especially if there is a statically allocated sequence just reserved for it somewhere.
Of course the best answer is not to bother with those other compilers, and stick to FTN95, but then my view is that FTN95 is the best in every respect, and others are free to differ.
Eddie |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Jan 15, 2018 3:34 pm Post subject: |
|
|
Paul Holden:
I am not sure about what you require, but how about something like this?
Code: | function center(strng)
implicit none
character(len=*) :: strng
character(len=(len(strng)+len_trim(strng))/2) :: center
!
! code to assemble the output string,
! with the correct number of leading blanks added and trailing blanks removed
!
end function center
|
You need to cut out leading blanks from the argument before passing the string to this function. If that is not desirable, or you wish to keep trailing blanks in the result string, you could adjust the length in the declaration of "center" to suit your needs.
Last edited by mecej4 on Mon Jan 15, 2018 4:40 pm; edited 2 times in total |
|
Back to top |
|
|
|