Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28446 Discussions

a way to determine the number of characters a formatted write "writes" ?

JP_SECTOR7_COM
New Contributor I
1,395 Views

 

string1 = 'abc'

string2 = 'def'

string3 = 'xx           '

WRITE (OPTEXT,FMT = "A,A,A")  string1 ,string2, string3

note that string3 will have multiple trailing spaces therefore TRIMing OPTEXT is not a viable option.

Also the formatted write may have varying levels of complexity so simply adding the length() of the string(s) is also not an option (as there could also be formatted numerics)

The "Q" formatter doesn't return the number of characters written to a string (only a file).

And there doesn't seem to be a function that returns the number of characters written by the WRITE.

INQUIRE also doesn't seem to have a viable option.

Thank you.

 

 

 

0 Kudos
1 Solution
JP_SECTOR7_COM
New Contributor I
1,312 Views

Actually - I was hoping for an ifort extension that would solve the problem.  

View solution in original post

0 Kudos
13 Replies
JP_SECTOR7_COM
New Contributor I
1,359 Views

This would have been nice if it didn't core dump. Surely if fortran supports variable length strings this should have worked ??

 

character(len=:), allocatable :: buffer

buffer = 'hello'

write (*,*) '[', buffer, ']'

write (buffer,1000) 23, 05

BANG !!

[hello]
forrtl: severe (66): output statement overflows record, unit -5, file Internal Formatted Write
Image PC Routine Line Source
k 000000000042966B Unknown Unknown Unknown
k 000000000040D8DC Unknown Unknown Unknown
k 0000000000403BCB Unknown Unknown Unknown
k 0000000000403962 Unknown Unknown Unknown
libc-2.19.so 00007F112B5A4B05 __libc_start_main Unknown Unknown
k 0000000000403869 Unknown Unknown Unknown

0 Kudos
FortranFan
Honored Contributor II
1,340 Views

@JP_SECTOR7_COM ,

Note the Fortran run-time exception can be a "good thing" in situations when coders don't have the discipline to error handle themselves.  Otherwise, one can employ 'IOSTAT=..' or 'ERR=..', etc. clauses to avoid what you call "core dump".

Separately you don't state what you're trying to do and your comments indicate too many edge cases with you may have in mind, so it'll be difficult for readers to provide meaningful replies.  It'll be also difficult to fathom what might one conceive of introducing in Fortran in a future revision, especially considering most coders would be generally happy with simple workarounds they can adopt for themselves for either UNFORMATTED writes with INQUIRE statement or given how cheap memory is these days to give them the answer "on the fly" for FORMATTED writes:

   character(len=:), allocatable :: s1, s2, s3, fwrt, sfmt
   double precision :: d
   logical :: b
   integer :: lenw
   s1 = 'abc'
   s2 = 'def'
   s3 = 'xx           '
   d = 1.23D0
   b = .false.
   inquire ( iolength=lenw ) s1, s2, s3, 23, 05, b, d
   print *, "Length for unformatted write in compiler-specific file IO units: ", lenw
   sfmt = "(3(A,1X),2(I5,1X),L0,1X,1PG14.7)"
   allocate( character(len=65536) :: fwrt )
   write( fwrt, fmt=sfmt ) s1, s2, s3, 23, 05, b, d
   print *, "Length of formatted write as number of characters: ", len_trim(fwrt)
   print *, "Output string: ", trim(fwrt)
end

 

Upon execution using Intel Fortran,

 Length for unformatted write in compiler-specific file IO units:  39
 Length of formatted write as number of characters:  45
 Output string: abc def xx               23     5    1.230000

 

FortranFan
Honored Contributor II
1,339 Views

Since your inquiry is general Fortran as opposed to anything specific to Intel compiler, you may also want to pose it here for other feedback and views:

https://fortran-lang.discourse.group/

0 Kudos
JP_SECTOR7_COM
New Contributor I
1,313 Views

Actually - I was hoping for an ifort extension that would solve the problem.  

0 Kudos
FortranFan
Honored Contributor II
1,290 Views

If you don't have support, you can purchase it with Intel and make a request for the facility what you're hoping for at the Intel Online Service Center:  https://supporttickets.intel.com/servicecenter?lang=en-US

Or, you can make a proposal with the Fortran community at https://github.com/j3-fortran/fortran_proposals

It will likely be a long or a perpetual wait though!

In the mean time, other readers interested in this might consider rolling their own workaround, something like this with a scratch file instead of an internal file:

   use, intrinsic :: iso_fortran_env, only : iostat_eor, iostat_end
   integer :: slen, lun, istat
   character(len=1) :: c
   open( newunit=lun, status="scratch", form="formatted", iostat=istat )
   if ( istat /= 0 ) stop
   write( lun, fmt="(*(a))" ) "abc", "def", "hello   "
   rewind( lun )
   slen = 0
   loop_read: do
      read( lun, fmt="(a)", advance="no", iostat=istat ) c
      select case ( istat )
         case ( iostat_eor, iostat_end )
            close ( lun )
            exit loop_read
         case default
            slen = slen + 1
      end select
   end do loop_read
   print *, "Length of output string: ", slen
end

Upon execution, the program response is:

 Length of output string:  14

 

 

0 Kudos
mecej4
Honored Contributor III
1,284 Views

If I am not mistaken (given the rather incomplete description of what is wanted, I could certainly be mistaken), the proposal 19-252r2.txt for allowing variable length, auto-allocated character strings for error messages, etc., would cover the facility requested in this thread.

Steve_Lionel
Honored Contributor III
1,266 Views

@mecej4 is correct - a feature planned for the next standard revision (dubbed 202X for now) adds the ability to specify a deferred-length allocatable character variable (as tried here) in an internal WRITE, causing the variable to be reallocated to the exact output length. Fortran 2018 doesn't support that, and you just get whatever the current length is.

I am confident in predicting that Intel won't be interested in an extension that will be superseded by the standard in the next few years. I also predict that they won't be interested in implementing what's in the draft before the standard is published, having been burned by that back in the DEC days.

mecej4
Honored Contributor III
1,235 Views

In the event that JP_SECTOR7_COM wants an interim solution, here is code that I think does what (s)he wanted, incorporating the ideas of the contributors to this thread.

  • I have used a NULL character as the guard character, but any suitable character could be used instead.
  • I have arbitrarily assumed that the output string will never be longer than 255 characters // NULL, but this can be adjusted.
  • The ideas used in the code could be used to write a subroutine or function that will do a formatted write to a temporary internal file, ascertain the length needed, allocate a character variable with that length, copy the string to that, and deallocate the temporary internal file.

 

program varstr
   implicit none
   character(len=:), allocatable :: s1, s2, s3, fwrt, sfmt
   double precision :: d
   logical :: b
   integer :: i
   s1 = 'abc'
   s2 = 'def'
   s3 = 'xx           '
   d = 1.23D0
   b = .false.
   sfmt = '(3(A,1X),2(I5,1X),L1,1X,1PG14.7,A1)'

  ! make it long enough or prepare for crash!
   allocate( character(len=256) :: fwrt )

   write( fwrt, fmt=sfmt ) s1, s2, s3, 23, 05, b, d,char(0)
   i = index(fwrt,char(0))
   print *, "Length of fwrt with trailing null removed: ",i-1
   print '(A)','                0         1         2         3         4         5'
   print '(A)','                0         0         0         0         0         0'
   print "(1x,A,A1,A,A1)", "Output string: ", '|',fwrt(1:i-1),'|'
   deallocate(fwrt)
end

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,206 Views

My link "here" in an earlier reply is broken, and I can no longer edit it. It was referencing the first reply from @JP_SECTOR7_COM in this thread.

0 Kudos
JP_SECTOR7_COM
New Contributor I
1,316 Views

Yes - that works UNLESS the last data item has trailing spaces then the len_trim will "trim" the trailing spaces


write (string, *) "hello      "

len_trim() will return 5 not 8

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,300 Views

Perform an internal formatted write with one modification to your format statement, that of adding ,A.

Then add to variable list "~" or some other character known not to be in your output.

You can then index for "~" and subtract 1.

Jim Dempsey

0 Kudos
mecej4
Honored Contributor III
1,349 Views

Your two posts ask two different questions, so the responses that you will read may be confusing.

Regarding the first question, the number of characters written:

"Number of characters written" is not a well-defined entity. We can talk about the length of the character variable or array before and after writing, but we may not ask about the internal details of how the Fortran RTL routines do the "writing" and expect a unique answer or any answer. The length of the record will depend on the declared lengths of the character variables, which you did not show.

It would be more useful if you stated your purpose in wanting to know. What is wrong with using LEN_TRIM on the string after it gets written?

Regarding the second question, variable length strings:

Some implementations of variable strings were published, but Fortran does not have them as a standard feature, although deferred length allocatable character variables can go a long way.

In your program, the variable buffer has been allocated with length 5 prior to executing the internal WRITE. If your format 1000 had, say, '(I2,I3)', the WRITE would have worked normally. If it had '(2I5)', the variable is not long enough, and the error that you saw would occur. If you had not caused buffer to be allocated by assigning a character constant as its value in a previous statement, the variable would have been unallocated when the internal WRITE was executed, and again the WRITE would have failed.

 

0 Kudos
JP_SECTOR7_COM
New Contributor I
1,317 Views

The goal is to be able to calculate the number of characters written to a character string including TRAILING SPACES.

len_trim will trim ALL of the spaces from the end of the string.

IF the compiler had behaved "properly" and the formatted write to a dynamic (ALLOCATABLE) string had worked then the resulting string length would have included the trailing spaces.

But - as it doesn't - it is not a solution.

it seems that it is impossible to calculate the number of bytes written to a string by a formatted write IF the data includes trailing spaces.

 

0 Kudos
Reply