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