- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When I am reading in a text file, say as follows:
read(5,100)line
100 format(A)
How can I tell how many characters were in the line I read in?
It blanks out the unread characters, so that obscures the actual length of
the input line. Otherwise I could set all the characters to "$" and see which ones
were not overridden when I read in the next line.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
BTW, as far as I can tell, it does not encode CRs or Line feeds, using that format.
So is there another way to read in the text to get that information?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Anything wrong with len_trim for your usage?
Please, there are many good references on Fortran, both published and on-line, which you might have taken the time to consult in your vaunted 40 years of experience.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Use non-advancing input along with the SIZE and IOSTAT specifiers.
[fortran]! Short line.
! A longer line - one that is longer than our buffer.
! This complete line is read into the_complete_line variable even though it is really really long.
PROGRAM GetLengthOfStringRead
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: IOSTAT_END
IMPLICIT NONE
CHARACTER(20) :: buffer
INTEGER :: stat
INTEGER :: sz
INTEGER :: unit
CHARACTER(:), ALLOCATABLE :: the_complete_line
CHARACTER(*), PARAMETER :: filename &
= '2013-10-22 GetLengthOfStringRead.f90'
OPEN( NEWUNIT=unit, FILE=filename, &
ACTION='READ', STATUS='OLD' )
! Get a short line
READ(unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=sz) buffer
PRINT "('stat was ',I0,', SIZE was ',I0,' and buffer was ""',A,'""')", &
stat, sz, buffer
! If we didn't hit the end of the record, then move to the next record.
IF (stat == 0) READ (unit, "()")
! Get a long line.
READ(unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=sz) buffer
PRINT "('stat was ',I0,', SIZE was ',I0,' and buffer was ""',A,'""')", &
stat, sz, buffer
! If we didn't hit the end of the record, then move to the next record.
IF (stat == 0) READ (unit, "()")
! Get the complete line.
the_complete_line = ''
DO
READ (unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=sz) buffer
PRINT "('stat was ',I0,', SIZE was ',I0,' and buffer was ""',A,'""')", &
stat, sz, buffer
IF (stat > 0) STOP 'Oops!' ! Some sort of error.
IF (stat == IOSTAT_END) STOP 'End of file!'
the_complete_line = the_complete_line // buffer(:sz)
IF (stat < 0) EXIT ! End of record.
END DO
PRINT "('The complete line was ""',A,'""')", the_complete_line
CLOSE(unit)
END PROGRAM GetLengthOfStringRead
[/fortran]
If you are using formatted stream access and you have an incomplete record at the end of a file the line reading thing might miss the data in that incomplete record, but I'm not sure how things are supposed to work in that case. The above seems to fit the behaviour of the compilers that I've played with recently.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bill,
I'm not sure what problems you have with your code example:
read (5,100) line
100 format (A)
nc = len_trim (line)
mc = len (line)
nx = 0 ; do i = 1, len_trim(line) ; if (line(i:i) /= ' ') nx = nx+1 ; end do
I've appended the following statistics, which might explain your problem:
"mc" is the length of the character string: line, so that if the information being read is longer than MC then the extra information will be lost. If this is your problem, the solution is to either use stream input or make "line" very big.
"nc" will be the position of the last non-blank character of line read. If the problem is you want to count training blanks (which is a problem for fortran input), again you have to go to stream input.
"nx" is the count of non-blank characters read into line.
If you want to know the length of the line, then adapting Ian's code to get the length of the next line could be useful. If you want to do a single pass read, then you need to allocate LINE to be bigger than needed.
Perhaps a routine that returns the maximum line length and the number of lines for a given file name would be a useful utility routine.
John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your suggestions -
Someone was being sarcastic about my experience, but I only did science/engineering code and that was with "ancient" versions of Fortran.
Anyway, the text being read in was a .TXT file with embedded line feeds and carriage returns. But testing for blanks would not solve the
problem, since english text has blanks between words as well.The text I refer to is something you would see in an E-mail, or an article in a book or on a Web site.
I will try some experimentation with your different suggestions, since this is a problem
I have never encountered before.
One curious thing - my E-mail showed over 40 replies but only two of you responded.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Someone mentioned (not in this forum) using STREAM input, but I don't see anything about that here.
Is that a particular type of file, or does that refer to any kind of file ?
The Fortran help was really pitiful about this topic.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you don't mind using an extension, you can do this:
READ (5,100) linelen, line
100 FORMAT (Q,A)
The Q format, on input, transfers to the next I/O list item the number of characters remaining in the current line.
I don't think stream I/O would make this much easier for you. You could read a character at a time and use the EOR= indication to see when you reached the end of a record.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bill,
You should be able to open the file for transparent access and read one character at a time. ( make this a function get_next_character () )
You can then build on this and test for <CR>=13 or <LF>=10 or other control characters (0:31) and then assemble lines of text and note the number of characters in each line. You can differentiate between DOS (CR + LF), Unix formats or others.
The following is an example from another compiler. (I can't see an example of transparent access in the ifort documentation.)
[fortran]! Open the text file as transparent
!
file_name = get_file_name ()
!
open (unit =11, &
file =file_name, &
status='OLD', &
form ='UNFORMATTED', &
access='TRANSPARENT', &
iostat=iostat)
write (*,2000) 'Opening file ',trim(file_name),' iostat = ',iostat
2000 format (a,a,a,i0)
!
! Read all characters
!
count_ic = 0
n = 0
nl = 0
nc = 0
na = 0
nz = 0
!
do
read (unit=11, iostat=iostat) c
if (iostat /= 0) exit
!
n = n + one
ic = ichar(c)
count_ic(ic) = count_ic(ic)+one
select case (ic)
case (10,13)
nl = nl + one ! line control characters ; 10:LF indicates end of line
case (0:9,11,12,14:31)
nc = nc + one ! control characters
case (32:126)
na = na + one ! normal character
case (127:256)
nz = nz + one ! other character
case default
write (*,*) 'Unrecognised character : ichar =',ic
end select
end do
[/fortran]
Once you see the types of control characters in the file, you can build on this and start assembling and reporting lines and line length.
John
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page