getvals(3f) - [M_strings:TYPE] read arbitrary number of REAL values
from a character variable up to size of VALUES() array
(LICENSE:PD)
subroutine getvals(line,values,icount,ierr)
character(len=*),intent(in) :: line
class(*),intent(out) :: values(:)
integer,intent(out) :: icount
integer,intent(out),optional :: ierr
GETVALS(3f) reads a relatively arbitrary number of numeric values from a character variable into a REAL array using list-directed input.
NOTE: In this version null values are skipped instead of meaning to leave that value unchanged
1,,,,,,,2 / reads VALUES=[1.0,2.0]
Per list-directed rules when reading values, allowed delimiters are comma, semi-colon and space.
the slash separator can be used to add inline comments.
10.1, 20.43e-1 ; 11 / THIS IS TREATED AS A COMMENT
Repeat syntax can be used up to the size of the output array. These are equivalent input lines:
4*10.0
10.0, 10.0, 10.0, 10.0
LINE A character variable containing the characters representing a list of numbers
VALUES() array holding numbers read from string. May be of type INTEGER, REAL, DOUBLEPRECISION, or CHARACTER. If CHARACTER the strings are returned as simple words instead of numeric values. ICOUNT number of defined numbers in VALUES(). If ICOUNT reaches the size of the VALUES() array parsing stops. IERR zero if no error occurred in reading numbers. Optional. If not present and an error occurs the program is terminated.
Sample program:
program demo_getvals
use M_strings, only: getvals
implicit none
integer,parameter :: longest_line=256
character(len=longest_line) :: line
real :: values(longest_line/2+1)
integer :: ios,icount,ierr
INFINITE: do
read(*,'(a)',iostat=ios) line
if(ios /= 0)exit INFINITE
call getvals(line,values,icount,ierr)
write(*,'(4(g0,1x))')'VALUES=',values(:icount)
enddo INFINITE
end program demo_getvals
Sample input lines
10,20 30.4
1 2 3
1
3 4*2.5 8
32.3333 / comment 1
30e3;300, 30.0, 3
even 1 like this! 10
11,,,,22,,,,33
Expected output:
VALUES= 10.0000000 20.0000000 30.3999996
VALUES= 1.00000000 2.00000000 3.00000000
VALUES= 1.00000000
VALUES=
VALUES= 3.00000000 2.50000000 2.50000000
2.50000000 2.50000000 8.00000000
VALUES= 32.3333015
VALUES= 30000.0000 300.000000 30.0000000
3.00000000
*getvals* WARNING:[even] is not a number
*getvals* WARNING:[like] is not a number
*getvals* WARNING:[this!] is not a number
VALUES= 1.00000000 10.0000000
VALUES= 11.0000000 22.0000000 33.0000000
John S. Urban
Public Domain
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
character(len=*), | intent(in) | :: | line | |||
class(*), | intent(out) | :: | values(:) | |||
integer, | intent(out) | :: | icount | |||
integer, | intent(out), | optional | :: | ierr |
subroutine getvals(line,values,icount,ierr)
! ident_62="@(#) M_strings getvals(3f) read arbitrary number of values from a character variable"
! JSU 20170831
character(len=*),intent(in) :: line
class(*),intent(out) :: values(:)
integer,intent(out) :: icount
integer,intent(out),optional :: ierr
character(len=:),allocatable :: buffer
character(len=len(line)) :: words(size(values))
integer :: ios, i, ierr_local,isize
isize=0
select type(values)
type is (integer); isize=size(values)
type is (real); isize=size(values)
type is (doubleprecision); isize=size(values)
type is (character(len=*)); isize=size(values)
end select
ierr_local=0
words=' ' ! make sure words() is initialized to null+blanks
buffer=trim(unquote(line))//"/" ! add a slash to the end so how the read behaves with missing values is clearly defined
read(buffer,*,iostat=ios) words ! undelimited strings are read into an array
icount=0
do i=1,isize ! loop thru array and convert non-blank words to numbers
if(words(i) == ' ')cycle
select type(values)
type is (integer); read(words(i),*,iostat=ios)values(icount+1)
type is (real); read(words(i),*,iostat=ios)values(icount+1)
type is (doubleprecision); read(words(i),*,iostat=ios)values(icount+1)
type is (character(len=*)); values(icount+1)=words(i)
end select
if(ios == 0)then
icount=icount+1
else
ierr_local=ios
write(ERROR_UNIT,*)'*getvals* WARNING:['//trim(words(i))//'] is not a number of specified type'
endif
enddo
if(present(ierr))then
ierr=ierr_local
elseif(ierr_local /= 0)then ! error occurred and not returning error to main program to print message and stop program
write(ERROR_UNIT,*)'*getval* error reading line ['//trim(line)//']'
stop 2
endif
end subroutine getvals