replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - BACKSPACE
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

BACKSPACE

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
simon



Joined: 05 Jul 2006
Posts: 299

PostPosted: Wed May 01, 2013 2:09 pm    Post subject: BACKSPACE Reply with quote

Imagine the following trivial dataset:

    A A 1
    BBB 2


I only want to read the numbers, but I need to read them in unformatted, and the leading text is of a consistent length, but is not a consistent number of words. I may not always want to read the first line.

Consider the following program to read the data. It skips line 1, and then reads the entire line to work out how long the leading string is (not shown). It then attempts to backspace to read line 2 again, but this time to skip over the text and then read in the data.

Code:
PROGRAM p
  REAL :: d
  CHARACTER(LEN=64) :: c
!
  OPEN (UNIT=11,FILE='external_file.txt',ACTION='read',FORM='formatted',STATUS='old')
  READ (UNIT=11,FMT=*)
  READ (UNIT=11,FMT='(A)') c
! ... some calculations to determine that '(A3)' will be adequate for skipping the leading string
  BACKSPACE (UNIT=11)
  READ (UNIT=11,FMT='(A3)',ADVANCE='no') c
  READ (UNIT=11,FMT=     *) d
  PRINT *, d
END PROGRAM p


This all works great, except if the line used to diagnose the length of the string is the last line in the file. If it is, using BACKSPACE works as long as the last line ends with a carriage return, but if it does not then BACKSPACE takes you a line earlier. Try reading the data at the top of this post in these two ways. Without a carriage return at the end of line 2, the program reads in line 1; with a carriage return it reads in line 2.

As far as I can tell, that's how it should be (FTN95 is doing what the standard says), but it would still be nice to know where I am in the file after invoking BACKSPACE. IOSTAT returns a zero in both cases. There are of course work-arounds such as reading the data from c rather than
backspacing at all, but I don't even know whether c has been long enough to read in the entire line of data. I could rewind and get back to this point again, but it may have taken a long time to find this location.

Anybody have any good ideas?[/code]
Back to top
View user's profile Send private message
brucebowler
Guest





PostPosted: Wed May 01, 2013 6:56 pm    Post subject: Reply with quote

Well to start, I'd read each line into a string and then work on that string with internal reads (and friends) and eliminate the use of backspace all together.

Cleaner (IMHO) and probably much faster...
Back to top
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed May 01, 2013 10:55 pm    Post subject: Reply with quote

This looks like a bug in FTN95.

When the last line of the file doesn't have a carriage return, this record can still be read. After this read, the "current record" should then be the End-of-file record.

A subsequent use of BACKSPACE should then position to the last line again.

On the NAG compiler your program gives 2.0 whether or not there is a carriage return or not on the last line.

With FTN95 I get 2.0 if there is a carriage return and 1.0 if there isn't.
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Wed May 01, 2013 10:57 pm    Post subject: Re: Reply with quote

brucebowler wrote:
Well to start, I'd read each line into a string and then work on that string with internal reads (and friends) and eliminate the use of backspace all together.


Are list-directed reads of internal files (characters) allowed?
_________________
Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Back to top
View user's profile Send private message
simon



Joined: 05 Jul 2006
Posts: 299

PostPosted: Thu May 02, 2013 4:40 am    Post subject: Reply with quote

Quote:
Well to start, I'd read each line into a string and then work on that string with internal reads (and friends) and eliminate the use of backspace all together.


I normally would, but the files may be massive. I only have to do one backspace, essentially to identify in what column the data start, and then I can read the rest of the file. If I had to read in every line as a string and then read the string, I would assume (but have not tested) that that would be less efficient. The other reason for avoiding reading in each line as a string is that I would have to impose a limit on the width of the file. In practice the limit may not be very restrictive if I define a large enough string, but in general I try to avoid imposing any limits other than those of the compiler.

Am interested to find out if David's assessment that this is a compiler bug is true ...
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Fri May 03, 2013 2:54 am    Post subject: Reply with quote

I would expect that doing a double read would have a minimal performance cost. Try it and you will be pleasently surprised.
The double read approach could be:
Code:
PROGRAM p
  REAL    :: d
  CHARACTER(LEN=64) :: c
  integer :: n, i, iostat, l
!
  OPEN (UNIT=11,FILE='external_file.txt',ACTION='read',FORM='formatted',STATUS='old')
!
!
  do i = 1, huge(i)
    READ (UNIT=11,FMT='(A)', iostat=iostat) c
     if (iostat/= 0) then
       write (*,*) 'file read error : iostat=',iostat
       exit
     end if
! ... some calculations to determine that '(A3)' will be adequate for skipping the leading string
    n = 4
    l = len_trim (c) 
    if (l < n) then
       write (*,*) 'no data in line',i
       cycle
     end if
!
    READ (c(n:), FMT=*, iostat=iostat) d
    PRINT *, i, d, l, iostat
  end do
!
end

Code:
! external_file.txt
aaa  1
abc 2
xxx 3

zz  4


Not sure of what happens if FMT=* and c(4:) is blank, ie l<4
You might want to enhance your test for n and l

If you need to get n from the last line only, then you could read the file, storing the last valid line for each read, then rewind and read all the file ?
Faster would be to store all lines in a character array,
ie character c(num_lines)*64
read (c(line_number)(n:), fmt=*, iostat=iostat) d ! should work

Not sure if you are saying you need all lines of data or only the last line ?

Using an internal read of "c" is definately better than a backspace, especially for a large file. The array c can have nearly 33,554,432 (2^25) lines if allocatable.

John
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Fri May 03, 2013 3:40 am    Post subject: Reply with quote

This example demonstrates storing the file as 1 pass read.
Alternatively you could do a 2-pass read to determine the number of lines, or
a single pass read to store only the last line

John
Code:
PROGRAM p
  REAL    :: d
  CHARACTER (LEN=64), allocatable, dimension(:) :: c
  CHARACTER (LEN=64) :: last_c
  integer :: n, i, iostat, l, last_line, max_lines
!
  OPEN (UNIT=11,FILE='external_file.txt',ACTION='read',FORM='formatted',STATUS='old')
!
  max_lines =30000000
  allocate ( c(max_lines) )
  write (*,*) 'c has',size (c) * 64,' bytes'
!
  do i = 1, max_lines
    READ (UNIT=11,FMT='(A)', iostat=iostat) c(i)
     if (iostat/= 0) then
       write (*,*) 'file read error at line',i,' : iostat=',iostat
       exit
     end if
    l = len_trim (c(i)) 
    if (l > 3) then
      last_line = i
      last_c = c(i)
    else
      write (*,*) 'no data in line',i
    end if
  end do
!
! ... some calculations to determine that '(A3)' will be adequate for skipping the leading string
    n = 4
    l = len_trim (c(last_line)) 
!
    READ (c(last_line)(n:), FMT=*, iostat=iostat) d
    PRINT *, last_line, d, l, i, iostat
!
end
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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