In Fortran, is it possible to print data in a tabular manner, without losing information, when more space is needed than specified?
For instance consider the program
! format.f90
program main
real(8) :: arr(5)
arr = [0.0, 1.111, 22.22, 333.3, 444444444444444444.44]
print '(F10.3)', arr
end program main
Then by default the output for the last entry will be replaced by stars, indicating the lack of space.
>> ifort format.f90 -o format.bin
>> ./format.bin
0.000
1.111
22.220
333.300
**********
By comparison, C-style format specifiers automatically increase the column width when required, e.g.
// format.c
#include <stdio.h>
int main () {
double arr[5] = {0.0, 1.111, 22.22, 333.3, 444444444444444444.44};
for(int i=0; i<5; i++) {
printf("%10.3f\n", arr[i]);
}
}
>> gcc format.c -o format.bin
>> ./format.bin
0.000
1.111
22.220
333.300
444444444444444416.000
Is it possible to obtain such behavior in Fortran with built-in features?
Options, that don't fulfill the requirements
G descriptor. The G descriptor allows reliably outputting data in a tabular well-readable format and automatically adds exponentials when needed. However, it also wastes space if the exponentials are not needed and it doesn't line up the comma. For example, when switching F10.3 for G11.4,"¶" (paragraph sign added for emphasis):
>> ifort format.f90 -o format.bin
>> ./format.bin
0.000 ¶
1.111 ¶
22.22 ¶
333.3 ¶
0.4444E+18¶
Building a formatting API based on the F0 specifier. The specifier F0.3 would allow variable-width output, but doesn't allow specifying a minimum width. This could be solved using a wrapper function akin to leftpad, but a built-in or widely-used solution would be preferable for a better chance of actually being used in a codebase. As an example:
! format.f90
program main
real(8) :: arr(5)
integer :: i
arr = [0.0, 1.111, 22.22, 333.3, 444444444444444444.44]
! more complicated print statement, because 'float2char'
! cannot be 'elemental' due to needing the 'alloctable' property.
print '(A)', (float2char('(F0.3)', 10, arr(i)), i=1,5)
contains
function float2char(format, width, value) result(r)
character(:), allocatable :: r
character(*), intent(in) :: format
integer, intent(in) :: width
real(8), intent(in) :: value
character(64) :: buffer ! better: calculate size from value?
write(buffer, format) value
allocate(character(max(width, len_trim(buffer))) :: r)
r(:) = trim(buffer) ! (:) needed to prevent reallocation in recent compilers
r(:) = adjustr(r)
end function float2char
end program main
>> ifort format.f90 -o format.bin
>> ./format.bin
.000
1.111
22.220
333.300
444444452740661248.000