Jason Blevins <jrble
...@sdf.lonestar.org> wrote:
> On Sep 17, 2009, at 9:46 AM, us
...@example.net wrote:
> > A Fortran version of strtok could be useful for breaking up the
> > strings that come from the cgi input. ( stuff looks like
> > &val1=abcd&val2=1234 )
> Here is a strtok implementation, courtesy of John Urban:
> http://fortranwiki.org/fortran/show/strtok
Here's my equivalent, which I've used for nearly 2 decades, as you can
see from the date. This doesn't try to mimic the C strtok (and doesn't
have its limitations either). It is in a much more native Fortran style.
It is a little more complicated than some because it does some things
that I regularly find useful. For example, it can tell the caller what
trailing delimitter it found. This can be useful, for example, to
distinguish between
somefield, someotherfield
versus
somefield=somevalue, someotherfield
Also, I have a bit of special handling for blanks. All the usage
information is in the argument comments. Note that most of the arguments
are optional.
This is normally in a module. It does reference one other routine of
mine, but I presume the function of error_halt should be obvious.
subroutine find_field (string, field, position, delims, delim, found)
!-- Find a delimitted field in a string.
!-- 15 Nov 90, Richard Maine.
!-------------------- interface.
character*(*), intent(in) :: string !-- The string input.
character*(*), intent(out) :: field
!-- The returned field. Blank if no field found.
integer, optional, intent(inout) :: position
!-- On entry, the starting position for searching for the
field.
!-- Default is 1 if the argument is not present.
!-- On exit, the starting position of the next field or
!-- len(string)+1 if there is no following field.
character*(*), optional, intent(in) :: delims
!-- String containing the characters to be accepted as
delimitters.
!-- If this includes a blank character, then leading blanks are
!-- removed from the returned field and the end delimitter may
!-- optionally be preceeded by blanks. If this argument is
!-- not present, the default delimitter set is a blank.
character*(*), optional, intent(out) :: delim
!-- Returns the actual delimitter that terminated the field.
!-- Returns char(0) if the field was terminated by the end of
!-- the string or if no field was found.
!-- If blank is in delimitters and the field was terminated
!-- by one or more blanks, followed by a non-blank delimitter,
!-- the non-blank delimitter is returned.
logical, optional, intent(out) :: found
!-- True if a field was found.
!-------------------- local.
character :: delimitter*1
integer :: pos, field_start, field_end, i
logical :: trim_blanks
!-------------------- executable code.
field = ''
delimitter = char(0)
pos = 1
if (present(found)) found = .false.
if (present(position)) pos = position
if (pos > len(string)) goto 9000
if (pos < 1) call error_halt('Illegal position in find_field')
!-- Skip leading blanks if blank is a delimitter.
field_start = pos
trim_blanks = .true.
if (present(delims)) trim_blanks = index(delims,' ') /= 0
if (trim_blanks) then
i = verify(string(pos:),' ')
if (i == 0) then
pos = len(string) + 1
goto 9000
end if
field_start = pos + i - 1
end if
if (present(found)) found = .true.
!-- Find the end of the field.
if (present(delims)) then
i = scan(string(field_start:), delims)
else
i = scan(string(field_start:), ' ')
end if
if (i == 0) then
field_end = len(string)
delimitter = char(0)
pos = field_end + 1
else
field_end = field_start + i - 2
delimitter = string(field_end+1:field_end+1)
pos = field_end + 2
end if
!-- Return the field.
field = string(field_start:field_end)
!-- Skip trailing blanks if blank is a delimitter.
if (trim_blanks) then
i = verify(string(field_end+1:), ' ')
if (i == 0) then
pos = len(string) + 1
goto 9000
end if
pos = field_end + i
!-- If the first non-blank character is a delimitter,
!-- skip blanks after it.
i = 0
if (present(delims)) i = index(delims, string(pos:pos))
if (i /= 0) then
delimitter = string(pos:pos)
pos = pos + 1
i = verify(string(pos:), ' ')
if (i == 0) then
pos = len(string) + 1
else
pos = pos + i - 1
end if
end if
end if
!---------- Normal exit.
9000 continue
if (present(delim)) delim = delimitter
if (present(position)) position = pos
return
end subroutine find_field
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain