From: Bart Vandewoestyne on 7 Oct 2009 10:39 I have config files with lines that look as follows: on 0.2 0.2 0.02 0.02 0.01 0.01 pulse 5.0e8 100e3 The number of spaces between items is arbitrary, and the number formatting is also arbitrarily chosen by the user. The number of numbers after 'pulse' can vary. I read this as: character(len=100) :: pointsource_string ... read(unit=my_unit, fmt="(A)", iostat=ios) pointsource_string But now I want to split pointsource_string in two, namely so that the two resulting strings are: on 0.2 0.2 0.02 0.02 0.01 0.01 pulse and 5.0e8 100e3 I have looked into my Fortran 95/2003 explained handbook, searching for a way to skip 7 'whitespace areas'... but i could not come up with an elegant method to split the string at the point where I want to split. Any suggestions on how to do this? Thanks, Bart -- "Share what you know. Learn what you don't."
From: dpb on 7 Oct 2009 10:45 Bart Vandewoestyne wrote: > I have config files with lines that look as follows: > > on 0.2 0.2 0.02 0.02 0.01 0.01 pulse 5.0e8 100e3 > > The number of spaces between items is arbitrary, and the number > formatting is also arbitrarily chosen by the user. The number of > numbers after 'pulse' can vary. > > I read this as: > > character(len=100) :: pointsource_string > ... > read(unit=my_unit, fmt="(A)", iostat=ios) pointsource_string > > But now I want to split pointsource_string in two, namely so that > the two resulting strings are: > > on 0.2 0.2 0.02 0.02 0.01 0.01 pulse > > and > > 5.0e8 100e3 > .... > Any suggestions on how to do this? idx = index(ps_string, 'pulse', back=.true.) + len('pulse')+1 left_str = ps_string(1:idx-1) rite_str = ps_string(idx:len_trim(ps_string) --
From: Bart Vandewoestyne on 7 Oct 2009 11:26 On 2009-10-07, dpb <none(a)non.net> wrote: > >> Any suggestions on how to do this? > > idx = index(ps_string, 'pulse', back=.true.) + len('pulse')+1 > left_str = ps_string(1:idx-1) > rite_str = ps_string(idx:len_trim(ps_string) Sorry... i forgot to mention that the text 'pulse' can also be something else and with a different length... so the above trick doesn't work for me. Regards, Bart -- "Share what you know. Learn what you don't."
From: Richard Maine on 7 Oct 2009 11:42 Bart Vandewoestyne <MyFirstName.MyLastName(a)telenet.be> wrote: > I have looked into my Fortran 95/2003 explained handbook, > searching for a way to skip 7 'whitespace areas'... but i could > not come up with an elegant method to split the string at the > point where I want to split. > > Any suggestions on how to do this? There isn't anything "magic". Just search for non-whitspace and then search for whitespace. Loop the appropriate number of times. See the index, scan, and verify intrinsics. If I were doing it, I'd use my find_field utility subroutine, copied below. This does other stuff as well. You don't need anything within an order of magnitude this long. It isn't that hard a job. But this is a subroutine that I already have and is suitable. I think most people who end up doing much in the way of character processing develop a personal collection of utility routines. It sure beats doing everything from scratch every time. (I pulled this from a module that includes a bunch of others as well). 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
From: The Star King on 7 Oct 2009 11:42
On Oct 7, 4:26 pm, Bart Vandewoestyne <MyFirstName.MyLastN...(a)telenet.be> wrote: > On 2009-10-07, dpb <n...(a)non.net> wrote: > > > > >> Any suggestions on how to do this? > > > idx = index(ps_string, 'pulse', back=.true.) + len('pulse')+1 > > left_str = ps_string(1:idx-1) > > rite_str = ps_string(idx:len_trim(ps_string) > > Sorry... i forgot to mention that the text 'pulse' can also be > something else and with a different length... so the above trick > doesn't work for me. > > Regards, > Bart > > -- > "Share what you know. Learn what you don't." I suggest character(30) :: data(10) integer i read (pointsource_string,*) (data(i),i=1,10) then data(1)=on, data(2)=0.2 etc (NB data(i) are all strings) you can then recombine the strings as you want lefts=trim(data(1))//trim(data(2))//... etc rights=trim(data(9))//trim(data(10)) (this will get rid of the white space between blocks of text) to convert to a number real f read(data(2),*) f |