How to do a one-line WRITE in fortran - fortran

Fortran newbie here. If I have doubles TIME and Y, and I want to output them to a file with unit unitid, but I want to shorten the format of the doubles, can I do this in one line? what i have below doesn't work since it defaults to format for the doubles that is too long.
WRITE(unitid,*) 'TIME:',TIME, 'Y:', Y;
Note that i am using a fortran library so formatted output using a FORMAT statement doesn't seem to work. Thanks.

Related

Meaning of a number in a Fortran format string [duplicate]

I can't figure out what in the world this "9999" is doing in front of the e20.8, in the label of this fortran write statement.
Is does not refer to any other line in the code. In other words, there isn't a line labeled 9999 to which it refers, elsewhere in the program.
write(11,'(9999e20.8)') (9999.0, i=1,2*(numant+numunique))
I'm boggled - I haven't found the answer from google web searches, although I think I get the general picture about write statement syntax and formatting.
Is this enough info provided to make sense?
It's a repetition count; the general format for a format code is (count)(type)(format), eg as described in this tutorial here.
Unlike C-based languages, unused formatting codes are simply ignored, so this line essentially says "write out as many real numbers in scientific format (with 8 digits after the decimal) as there are in the following output list". (If you don't like doing it this way, with a hardcoded "big enough" number, you'd have to programatically generate the format string to have the "right" repetition code.
The output list is an implied-do loop, which generates the number 9999.0 2*(numant+numuniqe) times.

Fortran variable formatting with FORMAT statement without angle brackets?

In converting some FORTRAN code to be compatible with the GNU Fortran compiler, I need to get rid of some of the variable formatting angle brackets (<>) and replace them with equivalent GNU accepted formatting.
The problem is, I'd like to do this while still using the FORMAT statement. The reason for this is that the format statements are very complex, multi-line statements with strings and so forth, so to determine the size of the string buffer necessary for a very large code with multiple instances of variable formatting is undesirable.
That is, I could replace
write(10,100)blah,blah...,blah
100 format(... <ii>i10, 'this and that ',
.../
...)
with
vfmt=''
write(vfmt,'(a,...,a)')'(',...,ii,'i10','this and that ',...,')'
write(10,vfmt)blah,blah...,blah
where vfmt is some very long string buffer, but I'd rather do this only as a last resort.
Is it possible to make the FORMAT statement partially variable? Something like
vfmt=''
write(vfmt,'(i0)')ii
write(10,100)blah,blah...,blah
100 format(..., vfmt//'i10',...)
I know from attempting this that this specific approach does not work.
Thanks.

fortran format specifier for complex number

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.

PGI Fortran integer format

I have an input text file that contains an integer record like:
1
which is read in Fortran code as:
read(iunit,'(i4)') int_var
which works fine with Gfortran, but the same code compiled with PGI Fortran Compiler expects a field 4 characters wide (the actual record is just 1 character) and throws an error. Now I know that the format specifies the width and this may or may not be correct behavior according to the Fortran standard, but my question is - is there a compiler option for PGI that would make it behave like Gfortran in this respect?
This 3rd party code I'm using has a lot (hundreds or thousands) of read statements like this and input data has a lot of records with "wrong" width so both modifying the code or the input data would require significant effort.
I don't think this is connected to blank. This read should not cause an error, unless you opened the file iunit with pad="no". Default is allways pad="yes", which causes the input record to be padded with blanks, if it is too short.
Are you sure, that you use correct input files, with correct line ends? There could be problems with text file that originate in Windows and in Unix the CR could be read in the input record. In this case using the unix2dos utility might help. You may try to read a character(4) string using the a4 edit descriptor to test for this.
Does PGI Fortran support the open keyword blank="null"? I think that this will change the read to the behavior that you want and minimize the modifications to the code. blank="null" versus blank="zero" doesn't seem to make a difference in gfortran 4.7.

passing table of floats as argument in c++ main

I have a c++ program, I would like the first argument of the main (argv[1]) to correspond to a table of float. Is it possible to do that??
I was thinking about putting in a string my floats separated with spaces (e.g. "1.12 3.23 4.32 1.1 ...")
Is there a way to automatically convert such a string into a table of floats? If I understand well the atof function converts a string into a double. So it seems it could be possible to split my string using the spaces and then convert each portion using atof.
This option does not seem to be very efficient to me? In addition it returns double and not float :(
So, is there a better way to pass table of float as argument of a c++ program ?
Thank you
A stringstream can do both the splitting at spaces and the parsing into a float.
std::stringstream ss(the_string);
std::vector<float> v(std::istream_iterator<float>(ss),
(std::istream_iterator<float>()));
// the extra parentheses here are ugly but necessary :(
How to obtain the string with the data depends on how large it is and where it is supposed to come from. Just keep in mind that in many systems the arguments passed to program are already split by spaces, putting each part in a different element of argv.
Save it in a text file, and then read it from the file when your program starts. I isn't worth it to pass it as a command-line argument.
The main() parameter list is as it is. You can pass the strings of your numbers as arguments to your program. The main function will have to parse its argument.
When you want to pass a space separated list of numbers in argv[1] you can use the strtok function to get the individual number strings and have to pass it to a conversion function.
When your conversion function returns a double you should check that the result can be represented by a float and cast the value to a float variable. But I would consider to use double as the internal representation.
In addition to Singer's answer:
The commandline should be used mainly by human, not computer. If you really need a table of values, use configuration file. You can always use human readable format for it.