 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sat Jul 11, 2015 4:01 pm Post subject: |
|
|
Roger,
It depends on how many times you want to do this conversion. If only once, then if I were you then I'd open the file in an editor, and change ever <space_char> into a comma, then import it into Excel and do a data into columns job.
If it were several times, you might be better in replacing the spaces with <TAB> and then print out from Word.
It's only worth doing in in Fortran if the program development time is worth the effort.
John knows the Fortran Standard better than I, but if it were worth the program development time, I might read each line into a single character variable, then parse it for all the <Space_char> values (you know that there are 8 of them. Then I'd read the relevant substrings as
INTEGER
INTEGER
INTEGER
3 INTEGERs in the date
3 INTEGERs in the time
INTEGER + 1 letter (N or S)
INTEGER + 1 letter (E or W)
INTEGER (is it?)
REAL
and then I'd have the values in a form you could operate with.
I'd also attempt to read the standard line that begins 'Signal Strength ...' and report an error if it wasn't there, plus I'd parse the numeral (7 in the example) and the date, and I'd also search for the 'Pa Pd ...' line to see that I was marching through the data file in the correct strides. |
|
Back to top |
|
 |
rogerh
Joined: 02 Nov 2014 Posts: 46 Location: Longmont, CO
|
Posted: Sat Jul 11, 2015 4:13 pm Post subject: |
|
|
Thanks but it's not an option.
This is a simple utility program to reformat the output of another program where changing the first program would be too difficult.
I just need to know that's causing the error 59 to pop up.
Roger |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sat Jul 11, 2015 8:11 pm Post subject: |
|
|
OK, Roger,
When you write a format such as:
Code: | 12 format ('a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a') |
all it contains is a string
'a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a'
and there is no information on what to read or how. To make matters worse, you had the numbers before the 'a' each time, which is a repeat count - although it didn't matter at all because it was all in a string, and the error message tells you that the format statement contains no info on how to read anything. That's why you get Error 59.
Take out the quotes to give you:
Code: | 12 format (a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a) |
and it begins to work, but now the '/' characters in the date terminate each line read, so that your output looks like:
Quote: | [FTN95/Win32 Ver. 7.20.0 Copyright (c) Silverfrost Ltd 1993-2015]
NO ERRORS [<READER> FTN95/Win32 v7.20.0]
Creating executable: C:\Fortran Programming\Demo_Progs\lgotemp@.exe
Program entered
Pa Pd D Earthquake UTC Dat Lat Lon Dep
93 100 3 1983 UTC Dat Lat Lon Dep
82 88 1 1992 UTC Dat Lat Lon Dep
81 87 1 2007 UTC Dat Lat Lon Dep
81 87 3 2002 UTC Dat Lat Lon Dep
|
In other words, you can't get past the first / with your approach.
More to the point, with a short data set, nothing appears in your output file as it hadn't finished writing when the program quit. I renamed your program READER.F90 and compiled it with:
FTN95 -lgo reader >rh
to pipe the output to a file. |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sat Jul 11, 2015 8:11 pm Post subject: |
|
|
OK, Roger,
When you write a format such as:
Code: | 12 format ('a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a') |
all it contains is a string
'a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a'
and there is no information on what to read or how. To make matters worse, you had the numbers before the 'a' each time, which is a repeat count - although it didn't matter at all because it was all in a string, and the error message tells you that the format statement contains no info on how to read anything. That's why you get Error 59.
Take out the quotes to give you:
Code: | 12 format (a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a) |
and it begins to work, but now the '/' characters in the date terminate each line read, so that your output looks like:
Quote: | [FTN95/Win32 Ver. 7.20.0 Copyright (c) Silverfrost Ltd 1993-2015]
NO ERRORS [<READER> FTN95/Win32 v7.20.0]
Creating executable: C:\Fortran Programming\Demo_Progs\lgotemp@.exe
Program entered
Pa Pd D Earthquake UTC Dat Lat Lon Dep
93 100 3 1983 UTC Dat Lat Lon Dep
82 88 1 1992 UTC Dat Lat Lon Dep
81 87 1 2007 UTC Dat Lat Lon Dep
81 87 3 2002 UTC Dat Lat Lon Dep
|
In other words, you can't get past the first / with your approach.
More to the point, with a short data set, nothing appears in your output file as it hadn't finished writing when the program quit. I renamed your program READER.F90 and compiled it with:
FTN95 -lgo reader >rh
to pipe the output to a file. |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sat Jul 11, 2015 8:55 pm Post subject: |
|
|
... and it needs to be something like this:
Code: | PROGRAM READER
character lin$*55, v$(9)*10, str*60
integer*4 nl, lk, list(10)
!
open (unit=13,file='ver510e.tce')
open (unit=14,file='rogerh.tce')
!
12 format (1X,a2,1x,a3,1x,a1,1x,a10,1x,
& a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a)
nl = 0
lk = 0
DO
read (13,*)
read (13,*)
read (13,'(a55)',err=10) lin$ ! SIGNAL LINE
write (14,'(1x,a55)') lin$
read (13,*)
read (13,'(a55)',err=10) lin$ ! LABEL LINE
write (14,'(1x,a55)') lin$
lk = 0
do while (lk <=20)
read (13,'(A)',end=10) str
k = 0 ! first column is a blank
do 5 i=1,10
do 3 j=k+1,60
if (str(j:j) .eq. ' ') then
list (i) = j
go to 4
endif
3 continue
4 k = j
5 continue
! write(*,*) list
do 8 i=1,9
v$(i) = str(list(i)+1:list(i+1))
8 continue
WRITE (14,12) v$(1),v$(2),v$(3),v$(4),v$(5),
& v$(6),v$(7),v$(8),v$(9)
nl = nl+1
lk = lk+1
end do
end do
10 continue
end |
(Converted to Fortran 77 because I can't deal with this new-fangled stuff!).
Also, there's no pretence to elegance in this ...
You have more work to do if you want the numbers to be right justified, as they would be if you read them as I suggested a few posts ago.
Eddie |
|
Back to top |
|
 |
rogerh
Joined: 02 Nov 2014 Posts: 46 Location: Longmont, CO
|
Posted: Sat Jul 11, 2015 10:03 pm Post subject: |
|
|
Litus;
Ok, this is starting to make sense. I didn't try what you said before because I didn't realize the significance of the "/". In TrueBasic, when you tell it to read 10 characters, it doesn't matter what's in them.
Thanks again!
Roger |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Sun Jul 12, 2015 2:34 am Post subject: |
|
|
I would make the program a bit more general by parsing each line and testing the first number being numeric. You could improve on this: Code: | character line*120, strings(10)*10
integer line_count, ns, nl, nb, iostat
logical numeric
nb = 0
nl = 0
do line_count = 1, huge(line_count)
!
read (13,fmt='(a)', iostat=iostat) line
if ( iostat /= 0) exit
if (len_trim(line) < 1) cycle
!
call parse_this_line (line, strings, ns, numeric)
!
if ( .not. numeric ) then ! start of new group (title or header)
if ( .not. (nl==0 .or. nl==20) ) write (*,*) "ERROR : unexpected end of previous block at", line_count
nl = 0
write (14,11) nl, line
11 format (i2,1X,a)
!
else
if (ns /= 9) write (*,*) "ERROR : unexpected error at", line_count
if (nl == 20) write (*,*) "ERROR : too many result lines at", line_count
nl = nl+1
write (14,12) nl, strings(1:ns)
12 format (i2,1X,a2,1x,a3,1x,a1,1x,a10,1x,a8,1x,a3,1x,a4,1x,a3,1x,a3,2x,a)
if (nl==20) then
nb = nb+1
write (*,*) "end of block",nb
end if
end if
end do
end
subroutine parse_this_line (line, strings, ns, numeric)
!
! return up to 10 blank seperated strings (9 expected)
character line*(*), strings(10)*10
integer ns
logical numeric
!
integer f,j, iostat
ns = 0
f = 1
do j = 1,len_trim(line)+1
if (line(j:j) /= ' ') cycle
if ( j == f ) then
f = j+1 ! i will be start of next string
else
ns = ns+1
strings(ns) = line(f:j)
f = j+1
if ( ns == 10) exit
end if
end do
!
! simple numeric test
j = ichar(strings(1)(1:1))
numeric = j >= ichar('0') .and. j <= ichar('9')
!
! better numeric test
read (strings(1), fmt='(i2)', iostat=iostat) j
numeric = j > 0 .and. iostat==0
end subroutine parse_this_line |
John |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Sun Jul 12, 2015 3:16 am Post subject: |
|
|
This simple code may suggest an easier approach, so as to not read multiple lines Code: | character v$(9)*10, line*120
integer*4 iostat
!
open (unit=13,file='ver510e.tce')
!
13 format (10(a6,'_'), i6)
DO
read (13,fmt='(a)', iostat=iostat) line
if ( iostat /= 0 ) exit
line = trim (line) // ' \'
v$ = '~'
read (line,*,iostat=iostat) v$
write ( *,13) v$,' iostat=',iostat
end do
end |
Appending \ stops the free format read, although iostat = -1 just indicates that not all 9 strings were supplied. |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Sun Jul 12, 2015 7:11 am Post subject: |
|
|
Eddie and Roger,
I got this line terminator wrong. / is the end of line character not \. ( until today I did not know that / was an available function for read (*,*) )
I went back to my previous parser and tested the sample data and it now works ok. read(line,*) fails.
My latest test code is: Code: | character v$(10)*10, line*120
integer*4 iostat, line_num, ns
logical numeric, parse
!
open (unit=13,file='roger.txt') ! ver510e.tce or xx.txt
!
13 format (10(a6,'_'), i6)
parse = .true.
DO LINE_NUM = 1, huge(line_num)
read (13,fmt='(a)', iostat=iostat) line
if ( iostat /= 0 ) exit
if ( parse ) then
write (*,*) ' '
write (*,*) 'parsing : ',trim(line)
call parse_this_line (line, v$, ns, numeric)
end if
line = trim (line) // ' @ /'
v$ = '~'
read (line,*,iostat=iostat) v$(1:9)
write ( *,13) v$(1:9),' iostat=',iostat
end do
end
subroutine parse_this_line (line, strings, ns, numeric)
!
! return up to 10 blank seperated strings (9 expected)
!
character line*(*), strings(10)*10
integer ns
logical numeric
!
integer f,j, iostat
!
f = len(line)
line(f:f) = ' ' ! patch for last character is ' '
!
ns = 0 ! strings found
f = 1 ! start of next string
!
do j = 1,len_trim(line)+1
if (line(j:j) /= ' ') cycle
if ( j == f ) then ! leading blank
f = j+1 ! f will be start of next string
else
ns = ns+1
strings(ns) = line(f:j)
write (*,11) ns, j-f, line(f:j)
11 format (2i3,2x,a)
f = j+1
if ( ns == size(strings)) exit
end if
end do
!
! simple numeric test
j = ichar(strings(1)(1:1))
numeric = j >= ichar('0') .and. j <= ichar('9')
!
! better numeric test
read (strings(1), fmt='(i2)', iostat=iostat) j
numeric = j > 0 .and. iostat==0
write (*,*) '-----',numeric
end subroutine parse_this_line |
The sample data is Code: | Roger
Signal Strength and Detection Date (UTC) 7 2015/06/04
Pa Pd D# Earthquake UTC Date Lat Lon Depth Mag
93 100 3 1983/12/22 04:11:30 12N 14W 8 6.3
82 88 1 1992/06/28 11:57:38 34N 117W 11 7.3
81 87 1 2007/06/02 21:34:58 23N 101E 10 6.1
81 87 3 2002/03/03 12:08:06 36N 70E 194 7.2 |
The test retrieves the data ok using parser and
shows the read error with reading date formats with read(line,*).
The parser does not work with quoted "long string", although that could be included.
John |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sun Jul 12, 2015 2:26 pm Post subject: |
|
|
Hi Roger,
'LitusSaxonicum' is a blog name, it means 'Saxon Shore' in Latin and is the Roman name for the SE England coastline. I'm still looking for a suitable avatar.
In Fortran, if you want to read 10 characters oblivious to what they are, read with A10, or if reading with a * format they need to be in quotes '1234567890' (or use double quotes, "1234567890").
Hi John,
You just did some of the difficult stuff. Thanks.
Eddie |
|
Back to top |
|
 |
mecej4
Joined: 31 Oct 2006 Posts: 1899
|
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Sun Jul 12, 2015 7:39 pm Post subject: |
|
|
Nice try, but it's a pun on 'canoe' and 'canute', and it doesn't reflect the famous King's devoutness and political influence. |
|
Back to top |
|
 |
rogerh
Joined: 02 Nov 2014 Posts: 46 Location: Longmont, CO
|
Posted: Mon Jul 13, 2015 3:44 am Post subject: Re: |
|
|
LitusSaxonicum wrote: | Hi Roger,
In Fortran, if you want to read 10 characters oblivious to what they are, read with A10, or if reading with a * format they need to be in quotes '1234567890' (or use double quotes, "1234567890").
|
Yes I got it to work that way but I have no control over the input format so I can't use the quotes. What I want to do is reformat and right justify the columns that contain variable length values.
I can think of ways to do it but it's a lot of extra work.
Roger |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Mon Jul 13, 2015 11:57 am Post subject: |
|
|
Quote: | It's a lot of work |
Haven't John and I done most of it?
If the character strings are left justified (and you want right), then use the TRIMR@ function (see the FTN77 library functions manual) to rotate the (sub)string until there are no trailing blanks.
e.g.
Code: | TEXT(1:3) = TRIMR@ (TEXT(1:3)) |
Eddie |
|
Back to top |
|
 |
rogerh
Joined: 02 Nov 2014 Posts: 46 Location: Longmont, CO
|
Posted: Mon Jul 13, 2015 1:21 pm Post subject: Re: |
|
|
LitusSaxonicum wrote: |
Haven't John and I done most of it? |
Indeed you have an I do appreciate it but what I meant was that it was a lot of extra work for the PC.
Quote: |
If the character strings are left justified (and you want right), then use the TRIMR@ function (see the FTN77 library functions manual) to rotate the (sub)string until there are no trailing blanks.
e.g.
Code: | TEXT(1:3) = TRIMR@ (TEXT(1:3)) |
Eddie |
Yes, I'm familiar with that part. Fortran was my first language; Fortran IV.
That was a long time ago. A lot has changed since then.
Roger |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|