Home > Archive > Fortran > April 2006 > removing chars from c strings
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
removing chars from c strings
|
|
| David Frank 2006-04-18, 4:03 am |
|
I posted below in comp.lang.pl1 and thought it might be informative here.
=========== begin snip ==============
I discovered CVF compiler allows a dynamic pointer connection,
and function below uses it to allow pack function to accept a string arg.
I dont recall seeing code using this technique before, and will make an
inquiry
in comp.lang.fortran about whether my use shows something not seen before.
! -------------------------
PROGRAM varying_cstring
integer :: n
character(100) :: s = ' The qu*ick brown fox ju**mps 'C
n = Remove_Ch(s,'*')
write (*,*) n,' |',s(1:n),'|'
stop ! outputs 27 | The quick brown fox jumps |
contains
! ----------------------
FUNCTION Remove_Ch(s,ch) RESULT (nc)
character(*) :: s
character :: ch, a(len(s))
integer :: nc, sloc ; pointer (sloc,a)
sloc = loc(s) ! dynamic connection a -> s
a = pack(a, a/=ch)
nc = index(s,char(0)) -1
END FUNCTION
END PROGRAM
| |
| Gary L. Scott 2006-04-18, 8:07 am |
| David Frank wrote:
> I posted below in comp.lang.pl1 and thought it might be informative here.
>
> =========== begin snip ==============
> I discovered CVF compiler allows a dynamic pointer connection,
> and function below uses it to allow pack function to accept a string arg.
> I dont recall seeing code using this technique before, and will make an
> inquiry
> in comp.lang.fortran about whether my use shows something not seen before.
>
> ! -------------------------
> PROGRAM varying_cstring
> integer :: n
> character(100) :: s = ' The qu*ick brown fox ju**mps 'C
>
> n = Remove_Ch(s,'*')
> write (*,*) n,' |',s(1:n),'|'
> stop ! outputs 27 | The quick brown fox jumps |
>
> contains
> ! ----------------------
> FUNCTION Remove_Ch(s,ch) RESULT (nc)
> character(*) :: s
> character :: ch, a(len(s))
> integer :: nc, sloc ; pointer (sloc,a)
>
> sloc = loc(s) ! dynamic connection a -> s
> a = pack(a, a/=ch)
> nc = index(s,char(0)) -1
> END FUNCTION
> END PROGRAM
>
>
>
Boy you can really do some nifty things with those extensions.
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| Herman D. Knoble 2006-04-18, 8:07 am |
| David: Thanks for the example.
For info, this works under Intel Fortran, ifort V9.x as well, but
with the warning message:
Warning: DFRemoveCh.f90, line 15: A DEC Fortran pointer variable has been explicitly
given a data type that is not the longest integer type associated with the current
platform. [SLOC]
integer :: nc, sloc ; pointer (sloc,a)
----------------------------------------^
Output:
27 | The quick brown fox jumps |
Skip Knoble
On Tue, 18 Apr 2006 06:18:04 GMT, "David Frank" <dave_frank@hotmail.com> wrote:
-|
-|I posted below in comp.lang.pl1 and thought it might be informative here.
-|
-|=========== begin snip ==============
-|I discovered CVF compiler allows a dynamic pointer connection,
-|and function below uses it to allow pack function to accept a string arg.
-|I dont recall seeing code using this technique before, and will make an
-|inquiry
-|in comp.lang.fortran about whether my use shows something not seen before.
-|
-|! -------------------------
-|PROGRAM varying_cstring
-|integer :: n
-|character(100) :: s = ' The qu*ick brown fox ju**mps 'C
-|
-|n = Remove_Ch(s,'*')
-|write (*,*) n,' |',s(1:n),'|'
-|stop ! outputs 27 | The quick brown fox jumps |
-|
-|contains
-|! ----------------------
-|FUNCTION Remove_Ch(s,ch) RESULT (nc)
-|character(*) :: s
-|character :: ch, a(len(s))
-|integer :: nc, sloc ; pointer (sloc,a)
-|
-|sloc = loc(s) ! dynamic connection a -> s
-|a = pack(a, a/=ch)
-|nc = index(s,char(0)) -1
-|END FUNCTION
-|END PROGRAM
-|
-|
| |
| Herman D. Knoble 2006-04-18, 7:04 pm |
| Also, if the line
character(100) :: s = ' The qu*ick brown fox ju**mps 'C
is changed to:
character(100) :: s = ' The qu*ick brown fox ju**mps '//char(0)
then the program also compiles and runs ok with Lahey LF95.
Skip
On Tue, 18 Apr 2006 09:22:53 -0400, Herman D. Knoble <SkipKnobleLESS@SPAMpsu.DOT.edu>
wrote:
-|David: Thanks for the example.
-|
-|For info, this works under Intel Fortran, ifort V9.x as well, but
-|with the warning message:
-|
-| Warning: DFRemoveCh.f90, line 15: A DEC Fortran pointer variable has been explicitly
-|given a data type that is not the longest integer type associated with the current
-|platform. [SLOC]
-| integer :: nc, sloc ; pointer (sloc,a)
-|----------------------------------------^
-|Output:
-| 27 | The quick brown fox jumps |
-|
-|Skip Knoble
-|
-|On Tue, 18 Apr 2006 06:18:04 GMT, "David Frank" <dave_frank@hotmail.com> wrote:
-|
-|-|
-|-|I posted below in comp.lang.pl1 and thought it might be informative here.
-|-|
-|-|=========== begin snip ==============
-|-|I discovered CVF compiler allows a dynamic pointer connection,
-|-|and function below uses it to allow pack function to accept a string arg.
-|-|I dont recall seeing code using this technique before, and will make an
-|-|inquiry
-|-|in comp.lang.fortran about whether my use shows something not seen before.
-|-|
-|-|! -------------------------
-|-|PROGRAM varying_cstring
-|-|integer :: n
-|-|character(100) :: s = ' The qu*ick brown fox ju**mps 'C
-|-|
-|-|n = Remove_Ch(s,'*')
-|-|write (*,*) n,' |',s(1:n),'|'
-|-|stop ! outputs 27 | The quick brown fox jumps |
-|-|
-|-|contains
-|-|! ----------------------
-|-|FUNCTION Remove_Ch(s,ch) RESULT (nc)
-|-|character(*) :: s
-|-|character :: ch, a(len(s))
-|-|integer :: nc, sloc ; pointer (sloc,a)
-|-|
-|-|sloc = loc(s) ! dynamic connection a -> s
-|-|a = pack(a, a/=ch)
-|-|nc = index(s,char(0)) -1
-|-|END FUNCTION
-|-|END PROGRAM
-|-|
-|-|
| |
| Steven G. Kargl 2006-04-18, 7:04 pm |
| In article <ww%0g.6343$sq5.5705@newsread2.news.atl.earthlink.net>,
"David Frank" <dave_frank@hotmail.com> writes:
> ! -------------------------
> PROGRAM varying_cstring
> integer :: n
> character(100) :: s = ' The qu*ick brown fox ju**mps 'C
character(100) :: s = ' The qu*ick brown fox ju**mps '//char(0)
> n = Remove_Ch(s,'*')
> write (*,*) n,' |',s(1:n),'|'
> stop ! outputs 27 | The quick brown fox jumps |
>
> contains
> ! ----------------------
> FUNCTION Remove_Ch(s,ch) RESULT (nc)
> character(*) :: s
> character :: ch, a(len(s))
> integer :: nc, sloc ; pointer (sloc,a)
integer :: nc
integer*8 sloc ! 64-bit address on 64-bit CPUs
pointer (sloc,a) ! Nonstandard Cray pointer
> sloc = loc(s) ! dynamic connection a -> s
> a = pack(a, a/=ch)
> nc = index(s,char(0)) -1
> END FUNCTION
> END PROGRAM
troutmask:kargl[210] gfortran -o z -fcray-pointer a.f90
troutmask:kargl[211] ./z
27 | The quick brown fox jumps |
--
Steve
http://troutmask.apl.washington.edu/~kargl/
| |
| Dick Hendrickson 2006-04-18, 7:04 pm |
|
Steven G. Kargl wrote:
> In article <ww%0g.6343$sq5.5705@newsread2.news.atl.earthlink.net>,
> "David Frank" <dave_frank@hotmail.com> writes:
>
>
>
> character(100) :: s = ' The qu*ick brown fox ju**mps '//char(0)
>
>
>
>
> integer :: nc
> integer*8 sloc ! 64-bit address on 64-bit CPUs
> pointer (sloc,a) ! Nonstandard Cray pointer
>
But why? Can't this be done with perfectly standard
conforming Fortran? Isn't it a risk to have to remember
what size to use for the pointer variable?
Doesn't
a = transfer(s,a)
a = pack(a, a/=ch)
s = transfer(a,s)
do the same thing without the need to "equivalence" a
and s? Writing it this way makes it obvious that the
function is modifying its argument. Pointers obscure this.
Dick Hendrickson
Experience is what lets you make new mistakes.
>
>
>
>
> troutmask:kargl[210] gfortran -o z -fcray-pointer a.f90
> troutmask:kargl[211] ./z
> 27 | The quick brown fox jumps |
>
| |
| Steven G. Kargl 2006-04-18, 7:04 pm |
| In article <cI81g.19028$az4.5114@bgtnsc04-news.ops.worldnet.att.net>,
Dick Hendrickson <dick.hendrickson@att.net> writes:
>
>
> Steven G. Kargl wrote:
>
> But why? Can't this be done with perfectly standard
> conforming Fortran? Isn't it a risk to have to remember
> what size to use for the pointer variable?
>
> Doesn't
> a = transfer(s,a)
> a = pack(a, a/=ch)
> s = transfer(a,s)
> do the same thing without the need to "equivalence" a
> and s? Writing it this way makes it obvious that the
> function is modifying its argument. Pointers obscure this.
>
Your three lines of standard conforming code works fine
with gfortran.
I wanted to see if gfortran's Cray pointer feature
worked. You don't have to remember what the size of the
pointer variable is with gfortran. it will tell you
if you get it wrong.
troutmask:kargl[205] gfortran -o z -fcray-pointer a.f90
In file a.f90:16
pointer (sloc,a)
1
Warning: Cray pointer at (1) has 4 bytes of precision; memory
addresses require 8 bytes.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
| |
| David Frank 2006-04-18, 7:04 pm |
|
"Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
news:cI81g.19028$az4.5114@bgtnsc04-news.ops.worldnet.att.net...
>
>
> Steven G. Kargl wrote:
>
> But why? Can't this be done with perfectly standard
> conforming Fortran? Isn't it a risk to have to remember
> what size to use for the pointer variable?
>
> Doesn't
> a = transfer(s,a)
> a = pack(a, a/=ch)
> s = transfer(a,s)
> do the same thing without the need to "equivalence" a
> and s? Writing it this way makes it obvious that the
> function is modifying its argument. Pointers obscure this.
>
> Dick Hendrickson
>
You have added 2 copy operations which arent necessary if pack is allowed to
process the
caller's string DIRECT.
| |
| Steven G. Kargl 2006-04-18, 7:04 pm |
| In article <Tv91g.6473$sq5.2442@newsread2.news.atl.earthlink.net>,
"David Frank" <dave_frank@hotmail.com> writes:
>
> "Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
> news:cI81g.19028$az4.5114@bgtnsc04-news.ops.worldnet.att.net...
>
> You have added 2 copy operations which arent necessary if pack
> is allowed to process the caller's string DIRECT.
And your point is?
Dick's version conforms The Fortran Standard. Your version is
not portable and consforms to no Fortran Standard. The fact
that I had to change your code to account for 64-bit address
as opposed to a 32-bit default interger kind clearly demonstrates
that you solution is inferior.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
| |
| David Frank 2006-04-18, 7:04 pm |
|
"Steven G. Kargl" <kargl@troutmask.apl.washington.edu> wrote in message
news:e23a9m$db1$1@gnus01.u.washington.edu...
> In article <Tv91g.6473$sq5.2442@newsread2.news.atl.earthlink.net>,
> "David Frank" <dave_frank@hotmail.com> writes:
>
> And your point is?
>
> Dick's version conforms The Fortran Standard. Your version is
> not portable and consforms to no Fortran Standard. The fact
> that I had to change your code to account for 64-bit address
> as opposed to a 32-bit default interger kind clearly demonstrates
> that you solution is inferior.
>
CRAY pointers are in ALL serious compilers and the current Fortran standard
supports the LOC aka C_LOC function, but if you prefer to add 2
unnecessary copy operations
thats fine..
| |
| Steven G. Kargl 2006-04-18, 7:04 pm |
| In article <xba1g.5685$Es3.2240@newsread3.news.atl.earthlink.net>,
"David Frank" <dave_frank@hotmail.com> writes:
>
> "Steven G. Kargl" <kargl@troutmask.apl.washington.edu> wrote in message
> news:e23a9m$db1$1@gnus01.u.washington.edu...
>
> CRAY pointers are in ALL serious compilers and the current Fortran standard
> supports the LOC aka C_LOC function, but if you prefer to add 2
> unnecessary copy operations
> thats fine..
>
LOC and POINTER are not in any Fortran Standard (ie., F66, F77,
F90, F95, or F2003). LOC is not an alias for C_LOC and POINTER
is not an alias for C_F_POINTER. If you want to change the goal
post by pointing to C_LOC, then write your code to use the ISO
C binding.
I also noticed you choose to ignore the portability issue with
your code.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
| |
| David Frank 2006-04-18, 7:04 pm |
|
"Steven G. Kargl" <kargl@troutmask.apl.washington.edu> wrote in message
news:e23bqv$e6o$1@gnus01.u.washington.edu...
> In article <xba1g.5685$Es3.2240@newsread3.news.atl.earthlink.net>,
> "David Frank" <dave_frank@hotmail.com> writes:
>
> LOC and POINTER are not in any Fortran Standard (ie., F66, F77,
> F90, F95, or F2003). LOC is not an alias for C_LOC and POINTER
> is not an alias for C_F_POINTER. If you want to change the goal
> post by pointing to C_LOC, then write your code to use the ISO
> C binding.
>
> I also noticed you choose to ignore the portability issue with
> your code.
>
If Dick Henderson says he cant translate my CVF F95 function to current
standard
using C_LOC, C_whatever, statement for statement without using his 2
copy operations,
I would believe him, however you I dont believe.
| |
| Steven G. Kargl 2006-04-18, 7:05 pm |
| In article <ERa1g.6509$sq5.5418@newsread2.news.atl.earthlink.net>,
"David Frank" <dave_frank@hotmail.com> writes:
>
> "Steven G. Kargl" <kargl@troutmask.apl.washington.edu> wrote in message
> news:e23bqv$e6o$1@gnus01.u.washington.edu...
>
> If Dick Henderson says he cant translate my CVF F95 function to
> current standard using C_LOC, C_whatever, statement for statement
> without using his 2 copy operations, I would believe him, however
> you I dont believe.
You don't believe what?
Your code is nonstandard and it is nonportable. I've already
demonstrated the nonportable claim. I leave it as exercise for
you to examine the various standards.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
| |
|
| > Can't this be done with perfectly standard
> conforming Fortran?
just to add mine, standard F95 for the function and its use F2003, a
single line and still using pack ..
character(100) :: s = ' The qu*ick brown fox ju**mps '
character :: ch='*'
write(6,*) Remove_Ch(s,ch)
CONTAINS
FUNCTION Remove_Ch(s,ch) RESULT(res)
character(*), INTENT(IN) :: s
character, INTENT(IN) :: ch
character(len=len(s)) :: res
write(res,'(999A1)') pack((/(s(i:i) ,i=1,LEN(s))/), &
(/(s(i:i).NE.ch,i=1,LEN(s))/) )
END FUNCTION Remove_Ch
END
Cheers,
Joost
| |
| Greg Lindahl 2006-04-18, 7:05 pm |
| In article <xba1g.5685$Es3.2240@newsread3.news.atl.earthlink.net>,
David Frank <dave_frank@hotmail.com> wrote:
>CRAY pointers are in ALL serious compilers
And they're different in subtle ways. PathScale's front end is the
CraySoft front-end, but we had to relax several restrictions on Cray
pointers to get some common codes to work.
-- greg
(employed by QLogic nee PathScale, not speaking for either.)
| |
| Dick Hendrickson 2006-04-18, 7:05 pm |
|
Greg Lindahl wrote:
> In article <xba1g.5685$Es3.2240@newsread3.news.atl.earthlink.net>,
> David Frank <dave_frank@hotmail.com> wrote:
>
>
>
>
> And they're different in subtle ways. PathScale's front end is the
> CraySoft front-end, but we had to relax several restrictions on Cray
> pointers to get some common codes to work.
>
Heck, it's worse than that. Back in the mid 80s, Cray had
two Fortran compilers. Cray pointers behaved differently
with the two compilers (granted, that was in pretty unusual
cases).
Today the major differences in Cray pointer implementations
(aside from how you declare them) are in how arithmetic is
done on them. Given a statement like
cray_pointer = cray_pointer + 1
some implementations add 1. Others add 4 or 8, following
the C style of doing address arithmetic by adding the
size of the pointee. It's a bugger to do a lot of that and
still be portable.
Dave's point about Cray Pointers being in all serious
compilers is obviously "true". But, like hyperbole, they
shouldn't often be used because not one person in a million
can get them right.
Dick Hendrickson
> -- greg
> (employed by QLogic nee PathScale, not speaking for either.)
>
>
| |
| Dick Hendrickson 2006-04-18, 7:05 pm |
|
David Frank wrote:
> "Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
> news:cI81g.19028$az4.5114@bgtnsc04-news.ops.worldnet.att.net...
>
>
>
> You have added 2 copy operations which arent necessary if pack is allowed to
> process the
> caller's string DIRECT.
>
>
That's true, but it's not really a problem, it's more of a
feature ;). On modern machines doing Fortran applications,
the cost of doing the copies won't be measureable. There
is simply no meaningful time spent taking out characters
from strings.
More importantly, your code arguable violates part of the
standard (aside from being non-standard). There is a
pretty hard and fast rule about not modifying things
(like dummy arguments) if they are known by two names.
Here your "equivalence" of "a" and "s" violates that
rule. A compiler that does copy-in/copy-out as the
argument passing scheme is likely to do the wrong thing.
True, it would be hard for a compiler to mess up this little
example. But, suppose the actual argument to remove_ch
wasn't a simple variable, but was a substring or structure
component. Or, suppose the function was a little more
complicated and called some helper routines and passed on
"a" and "s" as arguments. There is no guarantee that the
compiler will always do the right thing.
Doing it in the standard way ensures that the compiler will
at least try to get it right. If timing is really
critical, then non-standard ways can be tried.
Dick Hendrickson
| |
| glen herrmannsfeldt 2006-04-18, 7:05 pm |
| Dick Hendrickson <dick.hendrickson@att.net> wrote:
(snip about CRAYpointers)
(someone wrote)
[color=darkred]
> Heck, it's worse than that. Back in the mid 80s, Cray had
> two Fortran compilers. Cray pointers behaved differently
> with the two compilers (granted, that was in pretty unusual
> cases).
> Today the major differences in Cray pointer implementations
> (aside from how you declare them) are in how arithmetic is
> done on them. Given a statement like
> cray_pointer = cray_pointer + 1
> some implementations add 1. Others add 4 or 8, following
> the C style of doing address arithmetic by adding the
> size of the pointee. It's a bugger to do a lot of that and
> still be portable.
Many of the CRAY machines were word addressed so in most cases
adding 1 was correct.
I once saw an implementation of a finite state automaton that
stored the match bit in the low bit of pointer variables (in C)
assuming that integers were more than 1 addressable unit long.
The CRAY version uses the high bit instead.
-- glen
| |
|
| "Dick Hendrickson" <dick.hendrickson@att.net> wrote in message
news:dZc1g.19948$az4.10372@bgtnsc04-news.ops.worldnet.att.net...
> Doing it in the standard way ensures that the compiler will
> at least try to get it right. If timing is really
> critical, then non-standard ways can be tried.
If timing is critical, a standard way could be tried.
This would involve compacting in place,
as has already been demonstrated to OP,
and would be quicker and simpler
than the complicated "solutions" shown.
|
|
|
|
|