string_to_values Subroutine

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

John S. Urban

LICENSE

Public Domain

Arguments

Type IntentOptional 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

Contents

Source Code


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