I kind of know the behaviour of the data statement in fortran. However I don't know if there is any situation where it is prefered or it should be avoided
I personally like data statement when the initialization of my variables would be more clear with it than by normal assignment. For example:
type gene
character :: gene
integer :: depth
integer :: delta
end type
type(gene) :: pool(8)
! initializing in a data statement looks nicer in this case
data pool%gene / '#', 'U', 'R', '+', '-', '*', '/', '^'/
data pool%depth / 0 , 0 , 1 , 2 , 2 , 2 , 2 , 2 /
data pool%delta / 1 , 1 , 0 , -1 , -1 , -1 , -1 , -1 /
The data statement is not obsolescent. However, its use amongst executable statements has been obsolescent since Fortran 95. Appendix B of the latest Fortran standard gives details of obsolescent features.
B.3.5 DATA statements among executables. The statement ordering
rules allow DATA statements to appear anywhere in a program unit after
the specification statements. The ability to position DATA
statements amongst executable statements is very rarely
used, unnecessary, and a potential source of error.
On page 140 of Modern Fortran Explained (the green edition from 2011, not the newer red edition, which I don't have), Metcalf, Cohen & Reid write
We recommend using the type declaration statement rather than the data
statement, but the data statement must be employed when only part of
a variable is to be initialised.
Given that two of the authors are members of the WG5 (which is responsible for the development of Fortran --- actually maybe all three authors are members; I'm not sure about Michael Metcalf), we can say with a fair degree of certainty that the data statement should be avoided unless initialising part of a variable, before the executable statements in a program unit.
Related
This question has been covered somewhat in previous SO questions. However, previous discussions seem somewhat incomplete.
Fortran has several I/O statements. There is READ(*,*) and WRITE(*,*), etc. The first asterisk (*) is the standard asterisk designating an input or output from the keyboard to/from the screen. My question is about the second asterisk:
The second asterisk designates the format of the I/O elements, the data TYPE which is being used. If this asterisk is left unchanged, the fortran complier uses the default format (whatever that may be, based on the compiler). Users must use a number of format descriptors to designate the data type, precision, and so forth.
(1) Are these format descriptors universal for all Fortran compilers and for all versions of Fortran?
(2) Where can I find the standard list of these format descriptors? For example, F8.3 means that the number should be printed using fixed point notation with field width 8 and 3 decimal places.
EDIT: A reference for edit descriptors can be found here: http://fortranwiki.org/fortran/show/Edit+descriptors
First, as a clarification, the 1st asterisk in the READ/WRITE statement has a slightly different meaning than you state. For write, it means write to the default file unit (in linux world generally standard out), for read it means read from the default file unit (in linux world generally standard in), either of which may not necessarily be connected to a terminal screen or a keyboard.
The 2nd asterisk means use list directed IO. For read statements this is generally useful because you don't need a specified format for your input. It breaks up the line into fields separated by space or comma (maybe a couple others that aren't commonly used), and reads each field in turn into the variable associated with that field in the argument list, ignoring unread fields, and continuing onto the next line if not enough fields were read in (unless a line termination character \ is explicitly included).
For writes, it means the compiler is allowed to determine what format to write the variables out (I believe with no separator). I believe it is allowed to do this at run time, so that you are all but guaranteed that the value it is trying to write will fit into the format specifier used, so you can be assured that you won't get ******* written out. The down side is you have to manually include a separator character in your argument list, or all your numbers will run together.
In general, using list directed read is more of a convenience to the user, so they don't have to fit their inputs into rigidly defined fields, and list directed writes are a convenience to the programmer, in case they're not sure what the output will look like.
When you have a data transfer statement like read(*,*) ... it's helpful to understand exactly what this means. read(*,*) is equivalent to the more verbose read(unit=*, fmt=*). This second asterisk, as you have it, makes this read statement (or corresponding write statement) list-directed.
List-directed input/output, as described elsewhere, is a convenience for the programmer. The Fortran standards specify lots of constraints that the compiler must follow, but this language has things like "reasonable values", so allowing output to vary by compiler, settings, and so on.
Again, as described elsewhere, fine user control over the output (or input) comes with giving a format specification. Instead of read(*,fmt=*), something like read(*,fmt=1014) or read(*,fmt=format_variable_or_literal). I take it your question is: what is this format specification?
I won't go into details of all of the possible edit descriptors, but I will say in response to (2): you can find the list of those edit descriptors in the Fortran standard (Clause 10 of Fortran 2008 goes into all the detail) or a good reference book.
To answer (1): no, edit descriptors are not universal. Even across Fortran standards. Of note are:
The introduction of I0 (and other minimal-width specifiers) for output in Fortran 95;
The removal of the H edit descriptor in Fortran 95;
The introduction of the DT edit descriptor in Fortran 2003.
I'm attempting to modernize an old code (or at least make it a bit more understandable) but I've run into an odd format for a, uh, FORMAT statement.
Specifically, it's a FORMAT statement with Hollerith constants in it (the nH where n is a number):
FORMAT(15H ((C(I,J),J=1,I3,12H),(D(J),J=1,I3, 6H),I=1,I3,') te'
1,'xt' )
This messes with the syntax highlighting as it appears this has unclosed parenthesis. It compiles fine with this format statement as is, but closing the parenthesis causes a compiling error (using either the intel or gfortran compiler).
As I understand it, Hollerith constants were a creature of Fortran 66 and were replaced with the advent of the CHARACTERin Fortran 77. I generally understand them when used as something like a character, but use as a FORMAT confuses me.
Further, if I change 15H ((... to 15H ((... (i.e. I remove one space) it won't compile. In fact, it won't compile even if I change the code to this:
FORMAT(15H ((C(I,J),J=1,I3,12H),(D(J),J=1,I3, 6H),I=1,I3,') text' )
I would like this to instead be in a more normal (F77+) format. Any help is appreciated.
What you have are actually Hollerith edit descriptors, not constants (which would occur in a DATA or CALL statement), although they use the same syntax. F77 replaced Hollerith constants outright; it added char-literal edit descriptor as a (much!) better alternative, but H edit descriptor remained in the standard until F95 (and even then some compilers still accepted it as a compatibility feature).
In any case, the number before the H takes that number of characters after the H, without any other delimiter; that's why deleting (or adding) a character after the H screws it up. Parsing your format breaks it into these pieces
15H ((C(I,J),J=1,
I3,
12H),(D(J),J=1,
I3,
6H),I=1,
I3,
') te'
'xt'
and thus a modern equivalent (with optional spaces for clarity) is
nn FORMAT( ' ((C(I,J),J=1,', I3, '),(D(J),J=1,', I3, '),I=1,', I3
1,') text' )
or if you prefer you can put that text after continuation (including the parens) in a CHARACTER value, variable or parameter, used in the I/O statement instead of a FORMAT label, but since you must double all the quote characters to get them in a CHARACTER value that's less convenient.
Your all-on-one-line version probably didn't compile because you were using fixed-form, perhaps by default, and only the first 72 characters of each source line are accepted in fixed-form, of which the first 6 are reserved for statement number and continuation indicator, leaving only 66 and that statement is 71 by my count. Practically any compiler you will find today also accepts free-form, which allows longer lines and has other advantages too for new code, but may require changes in existing code, sometimes extensive changes.
I am learning Fortran because well, yeah, thought I'd learn it. However, I've found utterly no information on what the purpose of * is in print, read, etc:
program main
print *, "Hello, world!"
end program main
What is the purpose of this *? I've done some research however I don't think I understand it properly, I don't want to carry on learning until I actually know the point of *.
From what I've managed to find I think that it's some sort of format specifier, however, I don't understand what that means and I have no idea if I'm even correct. All the tutorials I've found just tell me what to write to print to the console but not what * actually means.
You are correct in that it is a format specifier.
There's a page on Wikibooks to do with IO and that states:
The second * specifies the format the user wants the number read with
when talking about the read statement. This applies to the write and print statements too.
For fixed point reals: Fw.d; w is the total number of spaces alloted for the number, and d is the number of decimal places.
And the example they give is
REAL :: A
READ(*,'(F5.2)') A
which reads a real number with 2 digits before and after the decimal point. So if you were printing a real number you'd use:
PRINT '(F5.2)', A
to get the rounded output.
In your example you're just printing text so there's no special formatting to do. Also if you leave the format specifier as * it will apply the default formatting to reals etc.
The print statement does formatted output to a special place (which we assume is the screen). There are three available ways to specify the format used in this output. One of these, as in the question, is using *.
The * format specifier means that the formatted output will be so-called list-directed output. Conversely, for a read statement, it will be list-directed input. Now that the term has been introduced you will be able to find many other questions here: list-directed input/output has many potentially surprising consequences.
Generally, a format specification item says how to format an item in the input/output list. If we are writing out a real number we'd use a format item which may, say, state the precision of the output or whether it uses scientific notation.
As in the question, when writing out a character variable we may want to specify the width of the output field (so that there is blank padding, or partial output) or not. We could have
print '(A20)', "Hello, world!"
print '(A5)', "Hello, world!"
print '(A)', "Hello, world!"
which offers a selection of effects. [Using a literal character constant like '(A)' is one of the other ways of giving the format.]
But we couldn't have
print '(F12.5)', "Hello, world!" ! A numeric format for a character variable
as our format doesn't make sense with the output item.
List-directed output is different from the above cases. Instead, (quote here and later from the Fortran 2008 draft standard) this
allows data editing according to the type of the list item instead of by a format specification. It also allows data to be free-field, that is, separated by commas (or semicolons) or blanks.
The main effect, and why list-directed is such a convenience, is that no effort is required on the part of the programmer to craft a suitable format for the things to be sent out.
When an output list is processed under list-directed output and a real value appears it is as though the programmer gave a suitable format for that value. And the same for other types.
But the crucial thing here is "a suitable format". The end user doesn't get to say A5 or F12.5. Instead of that latter the compiler gets to choose "reasonable processor-dependent values" for widths, precisions and so on. [Leading to questions like "why so much white space?".] The constraints on the output are given in, for example, Fortran 2008 10.10.4.
So, in summary * is saying, print out the following things in a reasonable way. I won't complain how you choose to do this, even if you give me output like
5*0
1 2
rather than
0 0 0 0 0 1 2
and I certainly won't complain about having a leading space like
Hello, world!
rather than
Hello, world!
For, yes, with list-directed you will (except in cases beyond this answer) get an initial blank on the output:
Except for new records created by [a special case] or by continuation of delimited character sequences, each output record begins with a blank character.
This question has been covered somewhat in previous SO questions. However, previous discussions seem somewhat incomplete.
Fortran has several I/O statements. There is READ(*,*) and WRITE(*,*), etc. The first asterisk (*) is the standard asterisk designating an input or output from the keyboard to/from the screen. My question is about the second asterisk:
The second asterisk designates the format of the I/O elements, the data TYPE which is being used. If this asterisk is left unchanged, the fortran complier uses the default format (whatever that may be, based on the compiler). Users must use a number of format descriptors to designate the data type, precision, and so forth.
(1) Are these format descriptors universal for all Fortran compilers and for all versions of Fortran?
(2) Where can I find the standard list of these format descriptors? For example, F8.3 means that the number should be printed using fixed point notation with field width 8 and 3 decimal places.
EDIT: A reference for edit descriptors can be found here: http://fortranwiki.org/fortran/show/Edit+descriptors
First, as a clarification, the 1st asterisk in the READ/WRITE statement has a slightly different meaning than you state. For write, it means write to the default file unit (in linux world generally standard out), for read it means read from the default file unit (in linux world generally standard in), either of which may not necessarily be connected to a terminal screen or a keyboard.
The 2nd asterisk means use list directed IO. For read statements this is generally useful because you don't need a specified format for your input. It breaks up the line into fields separated by space or comma (maybe a couple others that aren't commonly used), and reads each field in turn into the variable associated with that field in the argument list, ignoring unread fields, and continuing onto the next line if not enough fields were read in (unless a line termination character \ is explicitly included).
For writes, it means the compiler is allowed to determine what format to write the variables out (I believe with no separator). I believe it is allowed to do this at run time, so that you are all but guaranteed that the value it is trying to write will fit into the format specifier used, so you can be assured that you won't get ******* written out. The down side is you have to manually include a separator character in your argument list, or all your numbers will run together.
In general, using list directed read is more of a convenience to the user, so they don't have to fit their inputs into rigidly defined fields, and list directed writes are a convenience to the programmer, in case they're not sure what the output will look like.
When you have a data transfer statement like read(*,*) ... it's helpful to understand exactly what this means. read(*,*) is equivalent to the more verbose read(unit=*, fmt=*). This second asterisk, as you have it, makes this read statement (or corresponding write statement) list-directed.
List-directed input/output, as described elsewhere, is a convenience for the programmer. The Fortran standards specify lots of constraints that the compiler must follow, but this language has things like "reasonable values", so allowing output to vary by compiler, settings, and so on.
Again, as described elsewhere, fine user control over the output (or input) comes with giving a format specification. Instead of read(*,fmt=*), something like read(*,fmt=1014) or read(*,fmt=format_variable_or_literal). I take it your question is: what is this format specification?
I won't go into details of all of the possible edit descriptors, but I will say in response to (2): you can find the list of those edit descriptors in the Fortran standard (Clause 10 of Fortran 2008 goes into all the detail) or a good reference book.
To answer (1): no, edit descriptors are not universal. Even across Fortran standards. Of note are:
The introduction of I0 (and other minimal-width specifiers) for output in Fortran 95;
The removal of the H edit descriptor in Fortran 95;
The introduction of the DT edit descriptor in Fortran 2003.
Can I specify a format specifier for a complex number in fortran? I have a simple program.
program complx1
implicit none
complex :: var1
var1 = (10,20)
write (*,*) var1
write (*,'(F0.0)') var1
write (*,'(F0.0,A,F0.0)') real(var1), ' + i ' , aimag(var1)
end program complx1
Output:
( 10.0000000 , 20.0000000 )
10.
20.
10. + i 20.
I wanted to use inbuilt format for a+bi with some format specifier, instead of one did manually (second last line of program). Obviously F0.0 did not work. Any ideas?
EDIT:
I don't think this is a duplicate of post: writing complex matrix in fortran, which says to use REAL and AIMAG functions. I already used those functions and wondering whether there is an inbuilt format that can do the work.
An addendum to #francescalus' existing, and mostly satisfactory, answer. A format string such as
fmt = '(F0.0,SP,F0.0,"i")'
should result in a complex number being displayed with the correct sign between real and imaginary parts; no need to fiddle around with strings to get a plus sign in there.
There is no distinct complex edit descriptor. In Fortran 2008, 10.7.2.3.6 we see
A complex datum consists of a pair of separate real data. The editing of a scalar datum of complex type is specified by two edit descriptors each of which specifies the editing of real data.
In your second example, which you say "did not work", you see this formatting in action. Because the format had only one descriptor with no repeat count the values are output in distinct records (format reversion).
The first of your three cases is a very special one: it uses list-directed output. The rules for the output are
Complex constants are enclosed in parentheses with a separator between the real and imaginary parts
There is another useful part of the first rule mentioned:
Control and character string edit descriptors may be processed between the edit descriptor for the real part and the edit descriptor for the imaginary part.
You could happily adapt your second attempt, as we note that your "not working" wasn't because of the use of the complex variable itself (rather than the real and imaginary components)
write (*, '(F0.0,"+i",F0.0)') var1
This, though, isn't right when you have potentially negative complex part. You'll need to change the sign in the middle. This is possible, using a character variable format (rather than literal) with a conditional, but it perhaps isn't worth the effort. See another answer for details of another approach, similar to your third option but more robust.
Another option is to write a function which returns a correctly written character representation of your complex variable. That's like your third option. It is also the least messy approach when you want to write out many complex variables.
Finally, if you do have to worry about negative complex parts but want a simple specification of the variable list, there is the truly ugly
write(*,'(F0.0,"+i*(",F0.0,")")') var1
or the imaginative
character(19) fmt
fmt = '(F0.0,"+",F0.0,"i")'
fmt(8:8) = MERGE('+',' ',var1%im.gt.0)
write(*,fmt) var1
or the even better use of the SP control edit descriptor as given by High Performance Mark's answer which temporarily (for the duration of the output statement) sets the sign mode of the transfer to PLUS which forces the printing of the otherwise optional "+" sign. [Alternatively, this can be set for the connection itself in an open with the sign='plus' specifier.]
All this is because the simple answer is: no, there is no in-built complex edit descriptor.