Controlling newlines when writing out arrays in Fortran

喜夏-厌秋 提交于 2021-02-16 15:10:52

问题


So I have some code that does essentially this:

REAL, DIMENSION(31) :: month_data
INTEGER :: no_days
no_days = get_no_days()
month_data = [fill array with some values]
WRITE(1000,*) (month_data(d), d=1,no_days)

So I have an array with values for each month, in a loop I fill the array with a certain number of values based on how many days there are in that month, then write out the results into a file.

It took me quite some time to wrap my head around the whole 'write out an array in one go' aspect of WRITE, but this seems to work.

However this way, it writes out the numbers in the array like this (example for January, so 31 values):

  0.00000         10.0000         20.0000         30.0000         40.0000         50.0000         60.0000
  70.0000         80.0000         90.0000         100.000         110.000         120.000         130.000
  140.000         150.000         160.000         170.000         180.000         190.000         200.000
  210.000         220.000         230.000         240.000         250.000         260.000         270.000
  280.000         290.000         300.000

So it prefixes a lot of spaces (presumably to make columns line up even when there are larger values in the array), and it wraps lines to make it not exceed a certain width (I think 128 chars? not sure).

I don't really mind the extra spaces (although they inflate my file sizes considerably, so it would be nice to fix that too...) but the breaking-up-lines screws up my other tooling. I've tried reading several Fortran manuals, but while some of the mention 'output formatting', I have yet to find one that mentions newlines or columns.

So, how do I control how arrays are written out when using the syntax above in Fortran?

(also, while we're at it, how do I control the nr of decimal digits? I know these are all integer values so I'd like to leave out any decimals all together, but I can't change the data type to INTEGER in my code because of reasons).


回答1:


You probably want something similar to

WRITE(1000,'(31(F6.0,1X))') (month_data(d), d=1,no_days)

Explanation:

  • The use of * as the format specification is called list directed I/O: it is easy to code, but you are giving away all control over the format to the processor. In order to control the format you need to provide explicit formatting, via a label to a FORMAT statement or via a character variable.
  • Use the F edit descriptor for real variables in decimal form. Their syntax is Fw.d, where w is the width of the field and d is the number of decimal places, including the decimal sign. F6.0 therefore means a field of 6 characters of width with no decimal places.
  • Spaces can be added with the X control edit descriptor.
  • Repetitions of edit descriptors can be indicated with the number of repetitions before a symbol.
  • Groups can be created with (...), and they can be repeated if preceded by a number of repetitions.
  • No more items are printed beyond the last provided variable, even if the format specifies how to print more items than the ones actually provided - so you can ask for 31 repetitions even if for some months you will only print data for 30 or 28 days.

Besides,

  • New lines could be added with the / control edit descriptor; e.g., if you wanted to print the data with 10 values per row, you could do

    WRITE(1000,'(4(10(F6.0,:,1X),/))') (month_data(d), d=1,no_days)
    
  • Note the : control edit descriptor in this second example: it indicates that, if there are no more items to print, nothing else should be printed - not even spaces corresponding to control edit descriptors such as X or /. While it could have been used in the previous example, it is more relevant here, in order to ensure that, if no_days is a multiple of 10, there isn't an empty line after the 3 rows of data.

  • If you want to completely remove the decimal symbol, you would need to rather print the nearest integers using the nint intrinsic and the Iw (integer) descriptor:

    WRITE(1000,'(31(I6,1X))') (nint(month_data(d)), d=1,no_days)
    


来源:https://stackoverflow.com/questions/51534237/controlling-newlines-when-writing-out-arrays-in-fortran

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!