How do I detect the length of an input line?

How do I detect the length of an input line?

When I am reading in a text file, say as follows:


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.

9 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.

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?

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.

Use non-advancing input along with the SIZE and IOSTAT specifiers.

! 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
  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,  &
  ! 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 = ''
    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.
  PRINT "('The complete line was ""',A,'""')", the_complete_line
END PROGRAM GetLengthOfStringRead

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.


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.


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.

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.

imagem de Steve Lionel (Intel)

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.



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.)

!  Open the text file as transparent
      file_name = get_file_name ()
      open (unit  =11,               &
            file  =file_name,        &
            status='OLD',            &
            form  ='UNFORMATTED',    &
            access='TRANSPARENT',    &
      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
         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

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.


Faça login para deixar um comentário.