Project 2
Some languages, such as Python, can split a string on a specified delimiter character and return a list of strings. The delimiter is dropped. Write a program that can accomplish this.
This should be a function, but we have not yet covered subprograms, so you may write a monolithic program. If you wish to look ahead, write this as a function.
Ideally we would use varying-length strings, but for them to be really useful for this project, we would need an allocatable array of varying-length strings, which requires a derived type or use of more advanced intrinsics.
Print the result in Python format,
[sub1,sub2,sub3]
Sample solution
program splitter
character(len=256) :: input, temp
character(len=80), dimension(:), allocatable :: output
character :: delimiter, ch
integer :: i, ndelims, nchars, chunk
input="Sample ;string ;for ; this; project \n"
delimiter=';'
temp=""
!First count how many delimiters
do i=1,len(input)
if (input(i:i)==delimiter) then
ndelims=ndelims+1
endif
enddo
!Allocate the array
allocate(output(ndelims+1))
chunk=1
nchars=0
do i=1,len(input)
ch=input(i:i)
nchars=nchars+1
if (ch==delimiter) then
output(chunk)=trim(temp)
temp=""
nchars=0
chunk=chunk+1
endif
temp(nchars:nchars)=ch
enddo
output(chunk)=trim(temp)
write(*,'(a)',advance="no") "["
do i=1,size(output)-1
write(*,'(a,a)',advance="no") trim(output(i)),","
enddo
write(*,*) trim(output(size(output))),"]"
end program
Bonus Project
A consultant was given a program that has code to generate a
format string dynamically. In particular, it can print items that might be arrays, with the repeat value generated automatically.
For example, given n1=5, n2=1, n3=3 and a pattern ‘(#e15.8,#i5,#f8.2)’
the result would be ‘(5e15.8,1i5,3f8.2)’. However, it didn’t work if any of the n1, n2, n3 variables were two digits. The algorithm was convoluted and hard to understand. It did work for two digits if the programmer used two hash marks, e.g. ##e15.8, but that required hand-editing the several files with output routines to find every place she wanted to write out more than 9 array elements. The author of the original code didn’t use any character or string functions other than substrings. This would surely be implemented more generally with better use of strings. Your task is to come up with a way to do this. If you have time, come up with a way to handle a 0 (i.e. skip printing). Test your program carefully.
Hints. You do not need to use a variable-length string, but if not, be sure to declare a generously-sized set of strings (32 or even 64 characters, for example). If using a fixed-length string, remember that you will need to remove blank space. Test your program for n1=10, n2=2, n3=3. Try another pattern like
‘(#es12.4,#i2,#f15.7,#i4)’. Suggestion: use an allocatable array for the coefficients (both numerical and character). Use array size to make sure they match.
Sample solution
program formatter
real, dimension(10) :: A
real, dimension(3) :: B
integer :: i,m,dlen
character(len=32) :: formatstr, pattern, chunk
character(len=1) :: delimiter
integer, allocatable, dimension(:) :: nvars
character(len=4), allocatable, dimension(:) :: cn
A=[(real(i**2),i=1,10)]
B=[(real(j/2.),j=20,26,3)]
m=11
delimiter='#'
pattern='(#e15.3,#i6,#f15.7)'
numchars=len(pattern)
dlen=len(delimiter)
allocate(nvars(3))
nvars(1)=size(A)
nvars(2)=2
nvars(3)=size(B)
allocate(cn(size(nvars)))
do i=1,len(cn)
write(cn(i),'(i4)') nvars(i)
enddo
formatstr=''
chunk=''
n=1
do
m=index(pattern,delimiter)
if ( m==0 .or. len(pattern)==0 ) then
exit
else
chunk=pattern(:m-1)
pattern=pattern(m+dlen:)
if (nvars(n) /= 0) then
formatstr=trim(adjustl(formatstr))//trim(adjustl(chunk))//&
trim(adjustl(cn(n)))
else
continue
endif
n=n+1
endif
enddo
formatstr=trim(adjustl(formatstr))//trim(adjustl(pattern(:)))
deallocate(nvars,cn)
print *, formatstr
end program