public subroutine string_to_values(line, iread, values, inums, delims, ierr)
NAME
string_to_values(3f) - [M_strings:TYPE] read a string representing
numbers into a numeric array
(LICENSE:PD)
SYNOPSIS
subroutine string_to_values(line,iread,values,inums,delims,ierr)
character(len=*) :: line
integer :: iread
real :: values(*)
integer :: inums
character(len=*) :: delims
integer :: ierr
DESCRIPTION
This routine can take a string representing a series of numbers and
convert it to a numeric array and return how many numbers were found.
OPTIONS
LINE Input string containing numbers
IREAD maximum number of values to try to read from input string
RESULTS
VALUES real array to be filled with numbers
INUMS number of values successfully read (before error occurs
if one does)
DELIMS delimiter character(s), usually a space. must not be a
null string. If more than one character, a space must
not be the last character or it will be ignored.
IERR error flag (0=no error, else column number string starts
at that error occurred on).
EXAMPLE
Sample Program:
program demo_string_to_values
use M_strings, only : string_to_values
implicit none
character(len=80) :: s=' 10 20e3;3.45 -400.3e-2;1234; 5678 '
integer,parameter :: isz=10
real :: array(isz)
integer :: inums, ierr, ii
call string_to_values(s,10,array,inums,' ;',ierr)
call reportit()
call string_to_values('10;2.3;3.1416',isz,array,inums,' ;',ierr)
call reportit()
contains
subroutine reportit()
write(*,*)'string_to_values:'
write(*,*)'input string.............',trim(s)
write(*,*)'number of values found...',inums
write(*,*)'values...................',(array(ii),ii=1,inums)
end subroutine reportit
end program demo_string_to_values
Expected output
string_to_values:
input string............. 10 20e3;3.45 -400.3e-2;1234; 5678
number of values found... 6
values................... 10.0000000 20000.0000 3.45000005
-4.00299978 1234.00000 5678.00000
string_to_values:
input string............. 10 20e3;3.45 -400.3e-2;1234; 5678
number of values found... 3
values................... 10.0000000 2.29999995 3.14159989
AUTHOR
LICENSE
Arguments
Type |
Intent | Optional | Attributes |
|
Name |
|
character(len=*),
|
intent(in) |
|
|
:: |
line |
|
integer,
|
intent(in) |
|
|
:: |
iread |
|
real,
|
intent(inout) |
|
|
:: |
values(iread) |
|
integer,
|
intent(out) |
|
|
:: |
inums |
|
character(len=*),
|
intent(in) |
|
|
:: |
delims |
|
integer,
|
intent(out) |
|
|
:: |
ierr |
|
Source Code
subroutine string_to_values(line,iread,values,inums,delims,ierr)
!----------------------------------------------------------------------------------------------------------------------------------
! 1989,1997-12-31,2014 John S. Urban
! given a line of structure , string , string , string process each
! string as a numeric value and store into an array.
! DELIMS contain the legal delimiters. If a space is an allowed delimiter, it must not appear last in DELIMS.
! There is no direct checking for more values than can fit in VALUES.
! Quits if encounters any errors in read.
!----------------------------------------------------------------------------------------------------------------------------------
! ident_63="@(#) M_strings string_to_values(3f) reads an array of numbers from a numeric string"
character(len=*),intent(in) :: line ! input string
integer,intent(in) :: iread ! maximum number of values to try to read into values
real,intent(inout) :: values(iread) ! real array to be filled with values
integer,intent(out) :: inums ! number of values successfully read from string
character(len=*),intent(in) :: delims ! allowed delimiters
integer,intent(out) :: ierr ! 0 if no error, else column number undecipherable string starts at
!----------------------------------------------------------------------------------------------------------------------------------
character(len=256) :: delims_local ! mutable copy of allowed delimiters
integer :: istart,iend,lgth,icol
integer :: i10,i20,i40
real :: rval
integer :: ier
integer :: delimiters_length
!----------------------------------------------------------------------------------------------------------------------------------
delims_local=delims ! need a mutable copy of the delimiter list
if(delims_local == '')then ! if delimiter list is null or all spaces make it a space
delims_local=' ' ! delimiter is a single space
delimiters_length=1 ! length of delimiter list
else
delimiters_length=len_trim(delims) ! length of variable WITH TRAILING WHITESPACE TRIMMED
endif
!----------------------------------------------------------------------------------------------------------------------------------
ierr=0 ! initialize error code returned
inums=0 ! initialize count of values successfully returned
istart=0
!----------------------------------------------------------------------------------------------------------------------------------
lgth=0 ! lgth will be the position of the right-most non-delimiter in the input line
do i20=len(line),1,-1 ! loop from end of string to beginning to find right-most non-delimiter
if(index(delims_local(:delimiters_length),line(i20:i20)) == 0)then ! found a non-delimiter
lgth=i20
exit
endif
enddo
if(lgth == 0)then ! command was totally composed of delimiters
call journal('*string_to_values* blank line passed as a list of numbers')
return
endif
!----------------------------------------------------------------------------------------------------------------------------------
! there is at least one non-delimiter sub-string
! lgth is the column position of the last non-delimiter character
! now, starting at beginning of string find next non-delimiter
icol=1 ! pointer to beginning of unprocessed part of LINE
LOOP: dO i10=1,iread,1 ! each pass should find a value
if(icol > lgth) EXIT LOOP ! everything is done
INFINITE: do
if(index(delims_local(:delimiters_length),line(icol:icol)) == 0)then ! found non-delimiter
istart=icol
iend=0 ! FIND END OF SUBSTRING
do i40=istart,lgth ! look at each character starting at left
if(index(delims_local(:delimiters_length),line(i40:i40)) /= 0)then ! determine if character is a delimiter
iend=i40 ! found a delimiter. record where it was found
EXIT ! found end of substring so leave loop
endif
enddo
if(iend == 0)iend=lgth+1 ! no delimiters found, so this substring goes to end of line
iend=iend-1 ! do not want to pass delimiter to be converted
rval=0.0
call string_to_value(line(istart:iend),rval,ier) ! call procedure to convert string to a numeric value
if(ier == 0)then ! a substring was successfully converted to a numeric value
values(i10)=rval ! store numeric value in return array
inums=inums+1 ! increment number of values converted to a numeric value
else ! an error occurred converting string to value
ierr=istart ! return starting position of substring that could not be converted
return
endif
icol=iend+2 ! set to next character to look at
CYCLE LOOP ! start looking for next value
else ! this is a delimiter so keep looking for start of next string
icol=icol+1 ! increment pointer into LINE
CYCLE INFINITE
endif
enddo INFINITE
enddo LOOP
! error >>>>> more than iread numbers were in the line.
end subroutine string_to_values