В Фортране можно ли печатать данные в табличной форме, не теряя информацию, когда требуется больше места, чем указано?
Например, рассмотрим программу
! 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
Тогда по умолчанию вывод для последней записи будет заменен звездочками, указывающими на недостаток места.
>> ifort format.f90 -o format.bin
>> ./format.bin
0.000
1.111
22.220
333.300
**********
Для сравнения, спецификаторы формата в стиле C автоматически увеличивают ширину столбца при необходимости, например,
// 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
Возможно ли получить такое поведение в Fortran со встроенными функциями?
Опции, которые не удовлетворяют требованиям
G дескриптор. Дескриптор G
позволяет надежно выводить данные в табличном хорошо читаемом формате и автоматически добавляет экспоненты при необходимости. Однако, это также тратит впустую пространство, если экспоненты не необходимы, и это не выравнивает запятую. Например, при переключении F10.3
на G11.4,"¶"
(знак абзаца добавлен для выделения):
>> ifort format.f90 -o format.bin
>> ./format.bin
0.000 ¶
1.111 ¶
22.22 ¶
333.3 ¶
0.4444E+18¶
Создание API форматирования на основе спецификатора F0
. Спецификатор F0.3
допускает вывод переменной ширины, но не позволяет указывать минимальную ширину. Эту проблему можно решить, используя функцию-оболочку, похожую на leftpad , но встроенное или широко используемое решение будет предпочтительнее для большей вероятности фактического использования в базе кода. Как пример:
! 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